[Codeforces734E]Anton and Tree 树的直径

来源:互联网 发布:企业号码搜索软件 编辑:程序博客网 时间:2024/05/29 18:46

好神的题
做法:对于每一条边E(u,v),若两点颜色相同那么边权为0,否则为1,输出树的直径/2上取整
证明:
边权为0相当于将两个点并成一个点,那么树上的点相当于已经进行了黑白染色,对于树的直径,至少需要树的直径/2,上取整,才能染成同一颜色,做法即对直径的中点染色即可

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#define N 200050using namespace std;int dep[N],vis[N],a[N],mx,n,x,cnt;int h[N];struct Edge{ int a,b,v,next; }e[2*N];void add(int a,int b,int v) {    e[++cnt].a = a;    e[cnt].b = b;    e[cnt].v = v;    e[cnt].next = h[a];    h[a] = cnt;}void dfs(int u) {    vis[u] = 1;    if (dep[u] > mx) mx = dep[u] , x = u;     for (int i=h[u];i;i=e[i].next) {        int v = e[i].b; if (vis[v]) continue;        dep[v] = dep[u] + e[i].v; dfs(v);    }}int main() {    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&a[i]);    for (int i=1;i<=n-1;i++) {        int u,v; scanf("%d%d",&u,&v);        add(u,v,a[u]^a[v]);         add(v,u,a[u]^a[v]);    }    memset(dep,0,sizeof(dep));    memset(vis,0,sizeof(vis));    mx = 0 , dep[1] = 0 , dfs(1);    memset(dep,0,sizeof(dep));    memset(vis,0,sizeof(vis));    mx = 0 , dep[x] = 0 , dfs(x);    printf("%d\n",(mx+1)/2);    return 0;}
0 0
原创粉丝点击