题解 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;
}
不要妄图追上西坠的太阳,而是要在黎明前就等着它!
浙公网安备 33010602011771号