直接缩点,然后跑一次树的直径就好了....
至于跑树的直径
简易推导可得,原图的答案其实等价与两个最原点....
因为(得到答案)就像水流一样,...一层一层的...
然后就结束了

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
int n,tot,tt,tot2,maxl1=0,maxl2=0,maxl=0;
int h[MAXN],h2[MAXN],color[MAXN];//1 white 2 black
int belong[MAXN],dis[MAXN];
struct node{
int from,to,next;
}e[MAXN<<1],e2[MAXN<<1];
void init(){
tot=tt=tot2=0;
memset(h,-1,sizeof(h));
memset(h2,-1,sizeof(h2));
memset(belong,-1,sizeof(belong));
}
void add(int x,int y){
tot++;
e[tot].from=x;
e[tot].to=y;
e[tot].next=h[x];
h[x]=tot;
}
void dfs(int now,int fa){
if(belong[now]==(-1)){
tt++;
belong[now]=tt;
}
for(int i=h[now];i!=(-1);i=e[i].next){
if(e[i].to!=fa){
if(color[e[i].to]==color[now])belong[e[i].to]=belong[now];
dfs(e[i].to,now);
}
}
}
void add2(int x,int y){
tot2++;
e2[tot2].from=x;
e2[tot2].to=y;
e2[tot2].next=h2[x];
h2[x]=tot2;
}
int dfs2(int now,int fa){
if(dis[now]>dis[maxl]){
maxl=now;
}
for(int i=h2[now];i!=(-1);i=e2[i].next){
if(e2[i].to!=fa){
dis[e2[i].to]=dis[now]+1;
dfs2(e2[i].to,now);
}
}
}
int main(){
init();
cin>>n;
for(int i=1;i<=n;i++)cin>>color[i],color[i]++;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,1);
for(int i=1;i<=tot;i++){
if(belong[e[i].from]!=belong[e[i].to]){
add2(belong[e[i].from],belong[e[i].to]);
}
}
//找树的直径
memset(dis,0,sizeof(dis));
dfs2(1,1);
memset(dis,0,sizeof(dis));
maxl1=maxl;
dfs2(maxl1,maxl1);
cout<<(dis[maxl]+1)/2<<endl;
}
来源:https://www.cnblogs.com/shatianming/p/12307358.html
