• 2020 China Collegiate Programming Contest Qinhuangdao Site K题 Kingdom's Power


    题目链接

    https://codeforces.com/gym/102769/problem/K

    题意

    给定一颗树,1号节点为根节点,1号节点上有无数个士兵,每次操作可以将一个士兵移动到相邻节点,为将所有点遍历一次的最小操作数是多少?

    思路

    一个士兵从一号节点出发必定走到某个叶子节点,因此我们可以枚举所有的叶子节点来计算答案, 每个叶子节点的贡献要么从另一个叶子节点派士兵过来或者一号节点派士兵过来,为了保证这样的合法性,我们用dfs序遍历来遍历每个叶子节点,dfs时应当先走(子树中离根节点距离最远的叶子节点最小)的子树。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 50;
    vector<int> G[maxn];
    int du[maxn];
    ll sz_d[maxn];//子树中叶子节点离根节点最远的距离
    ll d[maxn]; //到根节点距离
    void dfs_d(int v, int fa){
        sz_d[v] = d[v];
        for(auto u : G[v]){
            if(u != fa){
                d[u] = d[v] + 1;
                dfs_d(u, v);
                sz_d[v] = max(sz_d[v], sz_d[u]);
            }
        }
    }
    bool cmp(const int &a, const int &b){
        if(sz_d[a] < sz_d[b]) return a > b;//优先走小的
        else return a < b;
    }
    vector<int> p;
    void dfs_x(int v, int fa){//dfs序
        p.push_back(v);
        sort(G[v].begin(), G[v].end(), cmp);
        for(auto u : G[v]){
            if(u != fa){
                dfs_x(u, v);
                p.push_back(v);
            }
        }
    }
    void init(int n){
        p.clear();
        for(int i = 0;i <= n;i++){
            G[i].clear();
            du[i] = sz_d[i] = d[i] = 0;
        }
    }
    int main()
    {
        std::ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
        int t;
        cin >> t;
        int cas = 0;
        while(t--){
            int n;
            cin >> n;
            for(int i = 2;i <= n;i++){
                int x;cin >> x;
                G[i].push_back(x);du[i]++;
                G[x].push_back(i);du[x]++;
            }
            dfs_d(1, 0);
            dfs_x(1, 0);
            ll cnt = 1;
            ll ans = 0;
            for(auto i : p){
                if(du[i] == 1){
                    ans += min(cnt, d[i]);
                    cnt = 0;
                }
                cnt++;
            }
            init(n);
            cout << "Case #" << ++cas << ": " << ans << "
    ";
        }
        return 0;
    }
    
    
  • 相关阅读:
    RPC
    动词 or 名词 :这是一个问题 【转载】
    js 如何清除setinterval
    封装动画特效
    飞入特效
    建字段_添加数据_生成json.php
    mybatis由浅入深day02_9.3.5使用生成的代码_9.4逆向工程注意事项
    mybatis由浅入深day02_9逆向工程
    mybatis由浅入深day02_8spring和mybatis整合
    mybatis由浅入深day02_7.4mybatis整合ehcache_7.5二级缓存应用场景_7.6二级缓存局限性
  • 原文地址:https://www.cnblogs.com/Carered/p/13846902.html
Copyright © 2020-2023  润新知