P3478 [POI2008]STA-Station

原题链接

考察:树形dp

想了半天没想出来怎么从父节点的深度和推到子节点深度和,我果然fw

思路:

        换根dp模板题.也称二次扫描法,第一次多用于预处理,第二次多用于计算答案.

        第一次dfs时,用子节点更新父节点,计算每个结点的子树结点个数,并计算当前假定根的深度和

        第二次dfs时,用父节点更新子节点.如图: 可以发现除了2的子树上点外,其余点的深度+1,2子树上的点深度全部-1. 由此推出方程f[v] = f[u]+n-sum[v]-sum[v]

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 1000010;
 6 int n,h[N],idx,sum[N];
 7 LL f[N],ans;
 8 struct Road{
 9     int fr,to,ne;
10 }road[N<<1];
11 void add(int a,int b)
12 {
13     road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
14 }
15 void dfs(int u,int fa)
16 {
17     sum[u] = 1; 
18     for(int i=h[u];i!=-1;i=road[i].ne)
19     {
20         int v = road[i].to;
21         if(v==fa) continue;
22         dfs(v,u);
23         f[u] = f[v]+sum[v];
24         sum[u]+=sum[v];
25     }
26 }
27 void dfs_up(int u,int fa)
28 {
29     for(int i=h[u];i!=-1;i=road[i].ne)
30     {
31         int v = road[i].to;
32         if(v==fa) continue;
33         f[v] = n-sum[v]+f[u]-sum[v];
34         dfs_up(v,u);
35     }
36 }
37 int main()
38 {
39     memset(h,-1,sizeof h);
40     scanf("%d",&n);
41     for(int i=1;i<n;i++)
42     {
43         int a,b; scanf("%d%d",&a,&b);
44         add(a,b); add(b,a);
45     }
46     dfs(1,-1);
47     dfs_up(1,-1);
48     for(int i=1;i<=n;i++) ans = max(f[i],ans);
49     for(int i=1;i<=n;i++)
50       if(ans==f[i])
51       {
52           printf("%d\n",i);
53           break;
54       }
55     return 0;
56 }

 

posted @ 2021-04-07 20:17  acmloser  阅读(37)  评论(0编辑  收藏  举报