题解 CF734E 【Anton and Tree】

\[\huge\mathcal{DESCRIPTION} \]

日期 2020年8月23日
编号 \(\texttt{CF734E}\)
算法 并查集强连通分量,缩点树的直径
来源 无名小题

\[\huge\mathcal{SOLUTION} \]

来讲讲大体的思路吧!

这道题目,我们首先要想到:

  • 把那些相同颜色的点缩到一起,并不会影响答案。

缩点如图(样例):

然后,似乎就豁然开朗了。
缩完点以后似乎变成了一道求树的直径问题?
求完树的直径之后,我们容易想到:

\[Ans=\biggl\lfloor\frac{Diamater+1}{2}\biggr\rfloor \]

\[\huge\mathcal{CODE} \]

#include<bits/stdc++.h>
#define MAX 1000001
using namespace std;
int TotalPoint;
int Count;
int Color[MAX];
int Block[MAX];
int First[MAX],Second[MAX];
vector< int >Edge[MAX];
vector< int >NewEdge[MAX];
inline void Shrink(int Now,int Father)
{
	if(Color[Now]==Color[Father])
	{
		Block[Now]=Block[Father];
	}
	else
	{
		NewEdge[Block[Father]].push_back(Block[Now]);
	}
	register int i;
	for(i=0;i<Edge[Now].size();i++)
	{
		register int Next;
		Next=Edge[Now][i];
		if(Next!=Father)
		{
			Shrink(Next,Now);
		}
	}
}
inline void Diamater(int Now,int Father)
{
	register int i;
	for(i=0;i<NewEdge[Now].size();i++)
	{
		register int Next;
		Next=NewEdge[Now][i];
		Diamater(Next,Father);
		if(First[Next]+1>=First[Now])
		{
			Second[Now]=First[Now];
			First[Now]=First[Next]+1;
		}
		else
		{
			if(First[Next]+1>Second[Now])
			{
				Second[Now]=First[Next]+1;
			}
		}
	}
}
int main(void)
{
	register int i;
	cin>>TotalPoint;
	for(i=1;i<=TotalPoint;i++)
	{
		Block[i]=i;
	}
	Color[0]=233;
	for(i=1;i<=TotalPoint;i++)
	{
		cin>>Color[i];
	}
	for(i=1;i<TotalPoint;i++)
	{
		register int U,V;
		cin>>U>>V;
		Edge[U].push_back(V);
		Edge[V].push_back(U);
	}
	Count=0;
	Shrink(1,0);
	Diamater(1,0);
	register int Ans;
	Ans=0;
	for(i=1;i<=TotalPoint;i++)
	{
		Ans=max(Ans,First[i]+Second[i]);
	}
	cout<<(Ans+1)/2<<endl; 
	return 0;
}

posted @ 2020-08-23 23:45  Bushuai_Tang  阅读(227)  评论(0编辑  收藏  举报