zoukankan      html  css  js  c++  java
  • Codeforces Round #389 (Div. 2) 752F(树的权值重心)

    题目大意

    给定2k个队伍分别住在2k个城市里,需要设定若干个城市,然后选取2个队伍要在它们的最短路径上设一个城市作为休息站

    要求设立最少的休息站,然后输出如何安排2个队伍

    首先若干个其实就是在坑人,实际上1个就可以了

    这一个点就是树的权值重心。

    权值重心的定义:若选取权值重心为根,则它的任意子树的权值和不会大于所有子树权值和的二分之一

    那么接下来证明权值重心是可行的

    只需要构造出来一组分组即可

    我是这么构造的

    先搜每一个子树,搜集齐k个点放到A,然后继续搜集剩下的点放到B,如果权值重心上也有队伍,那么就把它加到B

    然后依次输出A[i],B[i]即可

    这样做是可行的,因为任意子树的权值和不会大于所有子树权值和的二分之一。(稍微想想就可以知道啦)

    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
    const int maxn = 222222;
    vector<int> G[maxn];
    queue<int> Q[2];
    int f[maxn], v[maxn], sz[maxn], son[maxn];
    int n, k, x, y, X;
    
    void dfs(int x, int fa)
    {
        for(int i = 0; i < G[x].size(); i++)
        {
            int to = G[x][i];
            if(fa == to) continue;
            dfs(to, x);
            sz[x] += sz[to];
            son[x] = max(son[x], sz[to]);
        }
        son[x] = max(son[x], 2*k - sz[x]);
    }
    
    void dfs2(int x, int fa, int c)
    {
        if(!f[x] && Q[c-1].size() < k && v[x])
        {
            f[x] = c;
            Q[c-1].push(x);
        }
        for(int i = 0; i < G[x].size(); i++)
        {
            int to = G[x][i];
            if(fa == to) continue;
            dfs2(to, x, c);
        }
    }
    
    int main()
    {
        cin>>n>>k;
        for(int i = 1; i < n; i++)
        {
            cin>>x>>y;
            G[x].push_back(y);
            G[y].push_back(x);
        }
        for(int i = 1; i <= 2*k; i++) cin>>x, sz[x] = v[x] = 1;
        dfs(1, 0);
        for(int i = 1; i <= n; i++)
            if(son[i] <= k) X = i;
        cout<<1<<endl<<X<<endl;
        for(int i = 0; i < G[X].size(); i++)
        {
            if(Q[0].size() < k)
                dfs2(G[X][i], X, 1);
            if(Q[0].size() == k)
                dfs2(G[X][i], X, 2);
        }
        if(Q[1].size() == k-1) Q[1].push(X);
        while(!Q[0].empty())
        {
            cout<<Q[0].front()<<" "<<Q[1].front()<<" "<<X<<endl;
            Q[0].pop(); Q[1].pop();
        }
    }
  • 相关阅读:
    这些简单优化能让你的Win10流畅很多
    win7系统登录界面背景怎么修改?
    如何在win7下通过easyBCD引导安装Ubuntu14.04
    为什么我的电脑打不开便签?
    打开Word为什么会出现感叹号呢???
    图像变换原理
    运行
    php、前端开发(网站建设)环境搭建
    zend studio面板功能
    zend studio汉化
  • 原文地址:https://www.cnblogs.com/Saurus/p/6227283.html
Copyright © 2011-2022 走看看