Codeforces Global Round 16 E Buds Re-hanging
https://codeforces.com/contest/1566/problem/E
const int maxn = 2e5 + 10;
vector<int> g[maxn];
int f1 = 0, f2 = 0, ans = 0;
int sz[maxn];
//dfs判断每个点是bud还是lef还是other
//如果发现了一个bud,那么我们先把bud放到root下
//当拿掉了bud以后,它的父节点可能变成lef或者bud或者other
//如果父节点变成lef,就按lef返回,变成bud就按bud返回
//最后得到bud的数量f,如果除root外所有节点都在bud上,ans -= f - 1,否则就是ans -= f
//就是说每个bud都可以减少一个lef,但是如果一开始没有lef,第一个bud就不能减少lef
int dfs(int now, int fa) {
sz[now] = 0;
if(g[now].size() == 1) {//lef
ans ++;
return 1;
}
int son = 0, bud = 0;
for(auto it : g[now]) {
if(it == fa) continue;
int res = dfs(it, now);
if(res == 1) son ++;
else if(res == 2) bud ++;
}
if(son == g[now].size() - 1) {//bud
sz[now] = son + 1;
f1 ++;
return 2;
}
else {
if(bud == g[now].size() - 1) {//lef
if(now != 1) ans ++;
return 1;
}
else if(son + bud == g[now].size() - 1) {//bud
sz[now] = son + 1;
f1 ++;
return 2;
}
else return 0;
}
}
void run() {
int n; cin >> n;
f1 = f2 = ans = 0;
for(int i = 1; i <= n; ++ i) g[i].clear();
g[1].push_back(1);
for(int i = 1; i < n; ++ i) {
int u, v;
cin >> u >> v;
g[v].push_back(u);
g[u].push_back(v);
}
dfs(1, 1);
if(sz[1]) f1 --;
int sum = 0;
//for(int i = 1; i <= n; ++ i) cout << sz[i] << ' '; cout << '\n';
for(int i = 2; i <= n; ++ i) sum += sz[i];
if(sum == n - 1) ans -= f1 - 1;
else ans -= f1;
cout << ans << '\n';
return ;
}

浙公网安备 33010602011771号