Anton and Tree
作者:互联网
树的直径的好题。
首先可以想到把相邻的颜色相同的点合并起来,于是就得到了一棵任意一条边两端颜色都不相同的新树,这样一来操作的过程就是先找一个点,然后把它变成相反的颜色,于是所有和这个点相邻的点全部被这个点收购了;然后这个大点再向四周扩展,于是就这么一层一层地,于是发现从一个点开始操作的步数等于离它最远的那个点和它的距离,而这个的最小值应该是树的直径的一半,求就可以了。
实现上,题解给了一种有用的方法,考虑把一开始的树上相同颜色的点边赋值为0,不同颜色的边赋值为1,这样就不需要搞并查集了直接在原树上跑树的直径即可。
code
#include<bits/stdc++.h>
//#define feyn
const int N=200010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,a[N];
struct edge{
int t,v,next;
}e[N<<1];
int head[N],esum;
inline void add(int fr,int to,int val){
e[++esum]=(edge){to,val,head[fr]};head[fr]=esum;
}
int dis,pl;
inline void dfs(int wh,int fa,int ndis){
if(ndis>dis)dis=ndis,pl=wh;
for(int i=head[wh],th;i;i=e[i].next){
if((th=e[i].t)==fa)continue;
dfs(th,wh,ndis+e[i].v);
}
}
signed main(){
#ifdef feyn
freopen("in.txt","r",stdin);
#endif
read(m);int s1,s2;
for(int i=1;i<=m;i++)read(a[i]);
for(int i=1;i<m;i++){
read(s1);read(s2);
add(s1,s2,a[s1]!=a[s2]);
add(s2,s1,a[s1]!=a[s2]);
}
dfs(1,0,0);
dfs(pl,0,0);
printf("%d\n",(dis+1)/2);
return 0;
}
标签:颜色,int,Anton,Tree,wh,read,th,getchar 来源: https://www.cnblogs.com/dai-se-can-tian/p/16530971.html