首页 > 代码库 > Codeforces708C Centroids

Codeforces708C Centroids

题目链接

题意:给定一棵n个结点的树,问:对于每个结点,能否通过删除一条边并添加一条边使得仍是树,并且删除该结点后得到的各个连通分量结点数 <= n/2?

题解:树形dp,两遍dfs,第一遍dfs求得以各个结点为根的子树的结点数,以及各个结点下面切掉某条边后最多可切出多少个结点;

          第二遍dfs求得每个结点上面切掉某条边后最多可切出多少个结点。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 4e5+1;
 5 vector<int> ve[N];
 6 bool vis[N];
 7 int num[N], maxson[N], down[N], up[N];
 8 int n;
 9 void dfs(int x){
10     vis[x] = true;
11     num[x] = 1;
12     maxson[x] = 0;
13     down[x] = 0;
14     for(int i = 0; i < ve[x].size(); i++){
15         int y = ve[x][i];
16         if(vis[y]) continue ;
17         dfs(y);
18         num[x] += num[y];
19         maxson[x] = max(maxson[x], num[y]);
20         down[x] = max(down[x], num[y] <= n/2? num[y]: down[y]);
21     }
22 }
23 void debug(vector<int>& v){
24     puts("***");
25     cout << v.size() << endl;
26     for(int i = 0; i < v.size(); i++)
27         cout << v[i] <<  ;
28     puts("");
29     puts("****");
30 }
31 void dfs2(int f, int x){
32     vis[x] = true;
33     int tot = ve[x].size();
34     vector<int> tmp(tot), pre(tot), hou(tot);
35     for(int i = 0; i < tot; i++){
36         int y = ve[x][i];
37         if(vis[y]) tmp[i] = 0;
38         else
39             tmp[i] = num[y] <= n/2? num[y]:down[y];
40     }
41     for(int i = 0; i < tot; i++){
42         pre[i] = tmp[i];
43         if(i) pre[i] = max(pre[i], pre[i-1]);
44     }
45     for(int i = tot-1; i >= 0; i--){
46         hou[i] = tmp[i];
47         if(i != tot-1) hou[i] = max(hou[i], hou[i+1]);
48     }
49     for(int i = 0; i < tot; i++){
50         int y = ve[x][i];
51         if(vis[y]) continue ;
52         if(n-num[y] <= n/2)
53             up[y] = n-num[y];
54         else {
55             up[y] = up[x];
56             if(i+1 < tot)
57                 up[y] = max(up[y], hou[i+1]);
58             if(i-1 >= 0)
59                 up[y] = max(up[y], pre[i-1]);
60         }
61         dfs2(x, y);
62     }
63 }
64 
65 int main(){
66     int u, v; scanf("%d", &n);
67     for(int i = 1; i < n; i++){
68         scanf("%d%d", &u, &v);
69         ve[u].push_back(v), ve[v].push_back(u);
70     }
71     dfs(1);
72     memset(vis, 0, sizeof(vis));
73     dfs2(0, 1);
74     bool tag;
75 //    for(int i = 1; i <= n; i++)
76 //        cout << maxson[i] << ‘ ‘ << num[i] << ‘ ‘ << down[i] << ‘ ‘ << up[i] << endl;
77     for(int i = 1; i <= n; i++){
78         if(maxson[i] <= n/2&&n-num[i] <= n/2)//不用切
79             tag = true;
80         else if(n-num[i] > n/2)//要切上面
81             tag = n-num[i]-up[i] <= n/2;
82         else//要切下面
83             tag = maxson[i]-down[i] <= n/2;
84         putchar(tag+0);
85         putchar(i == n? \n: );
86     }
87     return 0;
88 }

 

Codeforces708C Centroids