zoukankan      html  css  js  c++  java
  • CodeForces-734E Anton and Tree 树的直径

    题目大意:

    给定一棵有n个节点的树,有黑点白点两种节点.
    每一次操作可以选择一个同种颜色的联通块将其染成同一种颜色
    现在给定一个初始局面问最少多少步可以让树变为纯色.

    题解:

    首先我们拿到这棵树时先将其缩点
    然后我们手中的树就变成了一棵黑白相间的黑白树.
    那么我们现在就是每次选择一个节点使其变色,都会使得这个节点相邻的所有节点合并进来.
    所以我们找度数最大的合并就好了啊
    我们现在把这棵树想象成由若干条路径组成的.
    那么我们每次合并都会使某些路径的长度最多减少2
    所以我们可以自然而然地想到一定是树的直径花费的操作次数最大.
    所以我们将一棵树化作一条链上面连着许多其他的分支的形式.

    手模几个样例就话发现答案实际上是([frac{len+1}{2}])len为直径长度.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 200010;
    int belong[maxn],nodecnt;
    int col[maxn];
    struct Graph{
        struct Edge{
    	int to,next;
        }G[maxn<<1];
        int head[maxn],cnt;
        void add(int u,int v){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
        }
    #define v G[i].to
        void dfs1(int u,int f){
    	if(col[u] != col[f]) belong[u] = ++ nodecnt;
    	else belong[u] = belong[f];
    	for(int i = head[u];i;i=G[i].next){
    	    if(v == f) continue;
    	    dfs1(v,u);
    	}return ;
        }
        int dis[maxn],p;
        void dfs2(int u,int f){
    	for(int i = head[u];i;i=G[i].next){
    	    if(v == f) continue;
    	    dis[v] = dis[u] + 1;
    	    dfs2(v,u);
    	}
    	if(dis[p] < dis[u]) p = u;
        }
    #undef v
    }g1,g2;
    int main(){
        int n;read(n);
        for(int i=1;i<=n;++i) read(col[i]);
        for(int i=1,u,v;i<n;++i){
    	read(u);read(v);
    	g1.add(u,v);g1.add(v,u);
        }belong[1] = ++ nodecnt;
        g1.dfs1(1,1);
        for(int u=1;u<=n;++u){
    	for(int i = g1.head[u];i;i=g1.G[i].next){
    	    if(belong[g1.G[i].to] != belong[u]){
    		g2.add(belong[u],belong[g1.G[i].to]);
    	    }
    	}
        }
        g2.dfs2(1,1);
        int u = g2.p;
        memset(g2.dis,0,sizeof g2.dis);
        g2.dfs2(u,u);
        int ans = (g2.dis[g2.p] + 1)/2;
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    OA项目之分页
    OA项目之弹出层中再弹出层
    OA项目之导入
    OA项目之导出
    git使用6步走
    配置 Docker 镜像站
    Taro随笔
    byte(C# 参考)
    MySQL 笔记
    HTTP 错误代码
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6613127.html
Copyright © 2011-2022 走看看