• Codeforces734 E. Anton and Tree


    传送门:>Here<

    题意:给出一颗树,节点不是黑色就是白色,每次可以将一个颜色相同的块变颜色,问最少变几次才能让其变为同色

    解题思路:

      我们考虑由于每一次都是把同样颜色的色块进行变色,因此同样颜色的色块可以看成一个点。所以我们先将同一个色块缩成一个点。

      然后我们有一个结论,我们最后的答案就是缩点完成的这棵树的直径+1再除以2.

      我们很容易发现,缩点完成以后的树相邻的两个点颜色一定是不同的,否则就能继续缩。因此我们可以每次选择直径中间的那个点,改变它的颜色,然后它就与周围的那些点融合成为一个新的点,然后再找到中间的,继续重复如上步骤。最后我们会发现,恰好是$(dis+1) / 2$次。这个证明不是很严谨,不过感性地理解一下吧

    Code

      细节不多

    /*by DennyQi*/
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b))?(a):(b))
    #define  Min(a,b)  (((a)<(b))?(a):(b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 200010;
    const int INF = 0x3f3f3f3f;
    const int MOD = 998244353;
    inline int read(){
        int x = 0; int w = 1; register unsigned char c = getchar();
        for(; c^'-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0';
        return x * w;
    }
    int N,cur_num;
    int color[MAXN],nod[MAXN],x[MAXN],y[MAXN],d[MAXN],vis[MAXN];
    vector <int> g[MAXN],G[MAXN];
    queue <int> q;
    inline void add(int u, int v){
        g[u].push_back(v);
    }
    inline void Add(int u, int v){
        G[u].push_back(v);
    }
    void dfs(int u){
        int sz = g[u].size(),v;
        nod[u] = cur_num;
        for(int i = 0; i < sz; ++i){
            v = g[u][i];
            if(!nod[v] && (color[v] == color[u])){
                dfs(v);
            }
        }
    }
    inline void BFS(int s){
        memset(d, 0x3f, sizeof(d));
        memset(vis,0,sizeof(vis));
        d[s] = 0;
        q.push(s);
        vis[s] = 1;
        int u,sz,v;
        while(!q.empty()){
            u = q.front();q.pop();
            sz = G[u].size();
            for(int i = 0; i < sz; ++i){
                v = G[u][i];
                if(!vis[v]){
                    vis[v] = 1;
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
    }
    int main(){
    //    freopen(".in","r",stdin);
        N=r;
        for(int i = 1; i <= N; ++i){
            color[i]=r;
        }
        for(int i = 1; i < N; ++i){
            x[i]=r,y[i]=r;
            add(x[i], y[i]);
            add(y[i], x[i]);
        }
        for(int i = 1; i <= N; ++i){
            if(!nod[i]){
                ++cur_num;
                dfs(i);
            }
        }
        for(int i = 1; i < N; ++i){
            if(nod[x[i]] != nod[y[i]]){
                Add(nod[x[i]], nod[y[i]]);
                Add(nod[y[i]], nod[x[i]]);
            }
        }
    /*    for(int i = 1; i <= cur_num; ++i){
            printf("%d: ", i);
            for(int j = 0; j < G[i].size(); ++j){
                printf("%d,",G[i][j]);
            }
            printf("
    ");
        }*/
        BFS(1);
        int _max = -1,p;
        for(int i = 1; i <= cur_num; ++i){
            if(d[i] > _max){
                _max = d[i];
                p = i;
            }
        }
    /*    printf("p = %d
    ", p);
        for(int i = 1; i <= cur_num; ++i){
            printf("%d ",d[i]);
        }
        printf("
    ");*/
        BFS(p);
        _max = -1;
        for(int i = 1; i <= cur_num; ++i){
            if(d[i] > _max){
                _max = d[i];
            }
        }
    /*    for(int i = 1; i <= cur_num; ++i){
            printf("%d ",d[i]);
        }
        printf("
    ");
        printf("_max = %d
    ", _max);*/
        printf("%d",(_max+1)/2);
        return 0;
    }
  • 相关阅读:
    ytu 2030: 求实数绝对值(水题)
    [PHP] 链表数据结构(单链表)
    PHP将数据写入指定文件中
    PHP获取文件后缀名
    PHP数组序列化和反序列化
    PHP二维数组(或任意维数组)转换成一维数组的方法汇总
    PHP获取文件大小的方法详解
    PHP中嵌套函数被调用时出现报错的问题
    PHP递归排序
    PHP实现简单倒计时
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9389722.html
Copyright © 2020-2023  润新知