给出一个树,若去掉其中一个结点,剩下的子树中规模最大的树的规模(估且称为D值),就是该点的D值。求所有结点中D值最小的点,输出点及其D值。

这题用两次DFS,第一次求出所有结点的子结点数,第二次求出所有结点的D值。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #define N 20005
 5 using namespace std;
 6 vector<int> ed[N];
 7 int s[N],w[N],n;
 8 int max(int a,int b)
 9 {
10     return a>b ?a :b ;
11 }
12 int dfs(int u, int fa)
13 {
14     int i;
15     s[u] = 1;
16     for(i = 0; i < ed[u].size(); i++)
17     if(ed[u][i] != fa)
18         s[u] += dfs(ed[u][i],u);
19     //printf("s[%d]:%d\n",u,s[u]);
20     return s[u];
21 }
22 void cal(int u, int fa)
23 {
24     int &ans = w[u],i,v,t=n-1;
25     ans = 0;
26     for(i = 0; i < ed[u].size(); i++)
27     if(ed[u][i] != fa)
28     {
29         v = ed[u][i];
30         cal(v,u);
31         t -= s[v];
32         if(s[v] > ans) ans = s[v];
33     }
34     ans = max(t,ans);
35     //printf("f(%d):%d\n",u,ans);
36 }
37 int main()
38 {
39     int T,a,b,i,min,f;
40     scanf("%d",&T);
41     while(T--)
42     {
43         scanf("%d",&n);
44         min = n;
45         for(i = 1; i <= n; i++) ed[i].clear();
46         for(i = 1; i < n; i++)
47         {
48             scanf("%d%d",&a,&b);
49             ed[a].push_back(b);
50             ed[b].push_back(a);
51         }
52         dfs(1,0);
53         cal(1,0);
54         for(i = 1; i <= n; i++)
55         if(w[i] < min)
56         {
57             min = w[i];
58             f = i;
59         }
60         printf("%d %d\n",f,min);
61     }
62     return 0;
63 }