题目链接:codeforces 734E
题目大意:
来看题解的都是知道题目是什么意思的,我就不多嘴了。
题解
cf自题解已经非常清楚了。
先缩点,再找出该树一条最长的直径d,答案就是(d+1)/2
为什么呐??
假设树的直径是0,那么答案就是0吧。
然后我们就可以看到这个事实: the tree diameter can’t be decreased more than by two per one painting operation with the “compression”. So the answer cannot be less than(d+1)/2 , where d is the tree diameter.(懒得翻译)
现在来证明它的正确性:Find such vertex that the shortest path from it to any other vertex doesn’t exceed (d+1)/2. Such vertex can always be found, because otherwise the tree diameter won’t be less that d + 1, which is impossible. Now see that if we paint this vertex (d+1)/2 times, we will paint the tree in one color.
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 200010
vector<int> g[N],gc[N];
bool vis[N];
int belong[N],col[N],dp[N];
int n,ans,u,v,cnt;
void dfs1(int u,int c,int rt)
{
if(vis[u] || col[u] != c) return;
vis[u] = 1;
belong[u] = rt;
for(int i = 0;i < g[u].size();i++)
dfs1(g[u][i],c,rt);
}
void dfs2(int u,int fa)
{
int mx = 0,mmx = 0;
for(int i = 0;i < gc[u].size();i++)
{
int v = gc[u][i];
if(v != fa)
{
dfs2(v,u);
mmx = max(mmx,dp[v]+1);
if(mmx > mx) swap(mmx,mx);
}
}
dp[u] = mx;
ans = max(ans,mx + mmx);
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++) scanf("%d",&col[i]);
for(int i = 1;i < n;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1;i <= n;i++)
if(!vis[i]) dfs1(i,col[i],++cnt);
for(int i = 1;i <= n;i++)
for(int j = 0;j < g[i].size();j++)
{
int v = g[i][j];
if(belong[v] != belong[i]) gc[belong[i]].push_back(belong[v]);
}
dfs2(1,-1);
printf("%d\n",(ans+1)/2);
return 0;
}