hdu4607 树直径(两次dfs求向下最远距离及另一方向最远距离相加)
之前有想过树的直径咋求,不过一直没仔细去考虑。
昨天做了hdu2196 今天突然想到如果把max(up[i]+dis1[i])求出来不就是直径maxx嘛==
随后百度了一下看到别人大多数是两次bfs,我从hdu上找了一道题目,果然是可以的。
思想应该是一样的吧,都是求两条最长路。
这题用到最长路还有:
1.k<=maxx+1那么就是k-1
2.k>maxx+1就是(k-maxx-1)*2+maxx+1因为要来回(thinking)
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 int next[200005],head[200005],point[200005],value[200005],now; 6 int dis1[200005],dis2[200005],id[200005],up[200005]; 7 void add(int x,int y,int w) 8 { 9 next[++now]=head[x]; 10 head[x]=now; 11 point[now]=y; 12 value[now]=w; 13 } 14 void dfs1(int pre,int u) 15 { 16 int i,v,w; 17 dis1[u]=dis2[u]=id[u]=0; 18 for (i=head[u];i;i=next[i]) 19 { 20 v=point[i]; w=value[i]; 21 if (v==pre) continue; 22 dfs1(u,v); 23 if (dis1[v]+w>dis1[u]){ 24 dis1[u]=dis1[v]+w; 25 id[u]=v; 26 } 27 } 28 for (i=head[u];i;i=next[i]) 29 { 30 v=point[i]; w=value[i]; 31 if (v==pre||v==id[u]) continue; 32 if (dis1[v]+w>dis2[u]) dis2[u]=dis1[v]+w; 33 } 34 } 35 void dfs2(int pre,int u) 36 { 37 int i,v,w; 38 for (i=head[u];i;i=next[i]) 39 { 40 v=point[i]; w=value[i]; 41 if (v==pre) continue; 42 up[v]=up[u]+w; 43 if (id[u]!=v) up[v]=max(up[v],dis1[u]+w); 44 else up[v]=max(up[v],dis2[u]+w); 45 dfs2(u,v); 46 } 47 } 48 int main() 49 { 50 int n,i,x,y,m,k,maxx,T; 51 scanf("%d",&T); 52 while (T--) 53 { 54 scanf("%d%d",&n,&m); 55 memset(head,0,sizeof(head)); 56 now=0; 57 for (i=2;i<=n;i++) 58 { 59 scanf("%d%d",&x,&y); 60 add(x,y,1); add(y,x,1); 61 } 62 memset(dis1,0,sizeof(dis1)); 63 memset(dis2,0,sizeof(dis2)); 64 memset(id,0,sizeof(id)); 65 dfs1(0,1); 66 memset(up,0,sizeof(up)); 67 dfs2(0,1); 68 maxx=0; 69 for (i=1;i<=n;i++) 70 maxx=max(maxx,up[i]+dis1[i]); 71 while (m--) 72 { 73 scanf("%d",&k); 74 if (k<=maxx+1) printf("%d\n",k-1); 75 else printf("%d\n",(k-maxx-1)*2+maxx); 76 } 77 } 78 return 0; 79 }