1. 程式人生 > 其它 >Codeforces Global Round 16 E Buds Re-hanging

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 ;
}