题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607
题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n)个点,至少需要走多少距离(每条边的距离是1);
思路:树形dp求树的直径r;
a:若k<=r+1 ,ans = k-1;
b:若k>=r+1,ans = r+(k-(r+1))*2;
代码:
1 #include "stdio.h" 2 #include "string.h" 3 4 #define N 110000 5 6 struct node 7 { 8 int x,y; 9 bool visit; 10 int next; 11 } edge[2*N]; 12 int idx,head[N]; 13 14 inline int MAX(int a,int b) 15 { 16 return a>b?a:b; 17 } 18 void Init() 19 { 20 idx=0; 21 memset(head,-1,sizeof(head)); 22 } 23 void Add(int x,int y) 24 { 25 edge[idx].x=x; 26 edge[idx].y=y; 27 edge[idx].visit=false; 28 edge[idx].next=head[x]; 29 head[x]=idx++; 30 } 31 32 int n; 33 int maxn[N],smaxn[N]; 34 35 void DFS(int x) 36 { 37 int i,y; 38 maxn[x] = smaxn[x] = 0; 39 for(i=head[x]; i!=-1; i=edge[i].next) 40 { 41 y = edge[i].y; 42 if(edge[i].visit) continue; 43 edge[i].visit = edge[i^1].visit = true; 44 DFS(y); 45 if(maxn[y]+1>maxn[x]) 46 { 47 smaxn[x] = maxn[x]; 48 maxn[x] = maxn[y]+1; 49 } 50 else if(maxn[y]+1>smaxn[x]) 51 smaxn[x] = maxn[y]+1; 52 } 53 } 54 55 int main() 56 { 57 int T,Q; 58 int i,j; 59 int x,y,k; 60 scanf("%d",&T); 61 while(T--) 62 { 63 Init(); 64 scanf("%d%d",&n,&Q); 65 for(i=1; i<n; ++i) 66 { 67 scanf("%d %d",&x,&y); 68 Add(x,y); 69 Add(y,x); 70 } 71 DFS(1); 72 int D=0; //树的直径 73 for(i=1; i<=n; ++i) 74 D = MAX(D,maxn[i]+smaxn[i]); 75 D++; 76 while(Q--) 77 { 78 scanf("%d",&k); 79 if(k<=D) 80 printf("%d ",k-1); 81 else 82 printf("%d ",D-1+(k-D)*2); 83 } 84 } 85 return 0; 86 }