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 ;
}
posted @ 2021-09-13 19:02  wlhp  阅读(56)  评论(0)    收藏  举报