原題連接node
分享題說實話最開始都沒什麼思路,以前的大部分基本都看了一下題解啓發思路。ios
但這道題我能夠大聲而驕傲地說:它 是 我 完 完 全 全 自 己 作 出 來 的 !ide
固然,代價就是Vjudge上WA了5遍,洛谷上WA了1遍,坑殺了我一節半課的時間。spa
那麼,轉到正題,思路是怎麼樣的呢?code
首先可見這個圖是一棵樹,咱們須要找到三個點,暫時叫ABC吧。其中(A到B的距離+C到AB距離中較短的)這一值最小。blog
(如下maxdis表明樹的直徑,maxv表明第一遍DFS找到的直徑端點,End表明第二遍DFS找到的另外一個端點,bj i表明點是否在直徑上,ans i 以及以後的ans1 i 表明節點 i 到maxv的距離,ans2 i 表明節點 i 到End的距離,b表明最後的答案)ci
很顯然這屬於樹的直徑題。用兩遍DFS找出樹的兩個頂點……以後呢?我在這裏第一次卡住了。get
因爲萬惡的樣例帶來的錯覺,我以爲題目要求的點必定是在直徑上。因此我就用了第三遍DFS,找出來了全部直徑上的點,在第二遍DFS的時候順帶計算出ans i,以後循環一遍找到答案就行。循環大概就是:string
for(int i=1;i<=n;i++) if(bj[i]==1&&i!=End&&i!=maxv) b=max(b,min(maxdis-ans[i],ans[i])); it
而後就WA了。
以後很長時間我就卡在了這個代碼的框框裏,由於我一直堅決地認爲要求的點在直徑上。卡了半天仍是感謝洛谷提供的一組錯誤樣例讓我恍然大悟:
個人C爲何必定要在直徑上?!
下面是洛谷給的樣例:
簡潔明瞭但頗有說服力。
顯然,樹的直徑是2-4或3-4。因爲這兩種沒有差異下面就用2-4舉例。
若是按照以前的想法,C在直徑上,那麼我算出來的結果是4.但若咱們選3做爲C呢?
2到4的距離+3到2,4距離中較短的=5。
也就是說C不必定在直徑上。
噫,好了,全崩了。
可是思路正確了應該就沒什麼問題了。咱們在第二遍dfs的時候順帶算出各點到maxv的距離,以後再DFS一遍算出各點到End的距離,以後把各個點遍歷一遍算min(ans1[i],ans2[i])+maxdis的最大值便可。
1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=200000+3; 10 int n,m,tot,head[maxn],End,maxv; 11 ll maxdis,ans1[maxn],ans2[maxn]; 12 struct node{ 13 int to,next; 14 ll w; 15 }e[2*maxn]; 16 void Add(int from,int to,ll w){ 17 e[tot].w=w; 18 e[tot].to=to; 19 e[tot].next=head[from]; 20 head[from]=tot; 21 tot++; 22 } 23 void dfs1(int u,int f,ll dis){//找第一個端點 24 if(maxdis<dis) { 25 maxv=u; 26 maxdis=dis; 27 } 28 for(int i=head[u];i;i=e[i].next){ 29 int v=e[i].to;ll w=e[i].w; 30 if(v==f) continue; 31 dfs1(v,u,dis+w); 32 } 33 } 34 void dfs2(int u,int f,ll dis){//找第二個端點 35 ans1[u]=dis;//順帶求出全部點到maxv的距離 36 if(maxdis<dis) { 37 maxdis=dis; 38 End=u; 39 } 40 for(int i=head[u];i;i=e[i].next){ 41 int v=e[i].to;ll w=e[i].w; 42 if(v==f) continue; 43 dfs2(v,u,dis+w); 44 } 45 } 46 void dfs3(int u,int f,ll dis){//求全部點到End的距離 47 ans2[u]=dis; 48 for(int i=head[u];i;i=e[i].next){ 49 int v=e[i].to;ll w=e[i].w; 50 if(v==f) continue; 51 dfs3(v,u,dis+w); 52 } 53 } 54 int main(){ 55 int n,m; 56 tot=1; 57 cin>>n>>m; 58 for(int i=1;i<=m;i++){ 59 int from,to;ll w; 60 cin>>from>>to>>w; 61 Add(from,to,w); 62 Add(to,from,w); 63 } 64 dfs1(1,-1,0); 65 maxdis=0; 66 dfs2(maxv,-1,0); 67 dfs3(End,-1,0); 68 ll b=-1; 69 for(int i=1;i<=n;i++) if(i!=End&&i!=maxv) b=max(b,min(ans1[i],ans2[i])+maxdis); 70 //找最佳點 71 cout<<b; 72 return 0; 73 }
幸甚至哉,歌以詠志。