ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CodeForces 734E-Anton and Tree(并查集缩点+树的直径)

2021-06-05 18:56:54  阅读:280  来源: 互联网

标签:734E 并查 int Anton tree vertices color d1


题目链接:https://codeforces.com/problemset/problem/734/E
博客园食用链接:https://www.cnblogs.com/lonely-wind-/p/13417220.html

Anton is growing a tree in his garden. In case you forgot, the tree is a connected acyclic undirected graph.

There are n vertices in the tree, each of them is painted black or white. Anton doesn’t like multicolored trees, so he wants to change the tree such that all vertices have the same color (black or white).

To change the colors Anton can use only operations of one type. We denote it as paint(v), where v is some vertex of the tree. This operation changes the color of all vertices u such that all vertices on the shortest path from v to u have the same color (including v and u). For example, consider the tree
在这里插入图片描述
and apply operation paint(3) to get the following:

Anton is interested in the minimum number of operation he needs to perform in order to make the colors of all vertices equal.

Input
The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of vertices in the tree.

The second line contains n integers color i (0 ≤ color i ≤ 1) — colors of the vertices. color i = 0 means that the i-th vertex is initially painted white, while color i = 1 means it’s initially painted black.

Then follow n - 1 line, each of them contains a pair of integers u i and v i (1 ≤ u i, v i ≤ n, u i ≠ v i) — indices of vertices connected by the corresponding edge. It’s guaranteed that all pairs (u i, v i) are distinct, i.e. there are no multiple edges.

Output
Print one integer — the minimum number of operations Anton has to apply in order to make all vertices of the tree black or all vertices of the tree white.

Examples
Input
11
0 0 0 1 1 0 1 0 0 1 1
1 2
1 3
2 4
2 5
5 6
5 7
3 8
3 9
3 10
9 11
Output
2
Input
4
0 0 0 0
1 2
2 3
3 4
Output
0
Note
In the first sample, the tree is the same as on the picture. If we first apply operation paint(3) and then apply paint(6), the tree will become completely black, so the answer is 2.

In the second sample, the tree is already white, so there is no need to apply any operations and the answer is 0.

题目大意:给你n个点构成一棵树,点由01两种颜色组成,现在你可以将相同颜色的联通区域改变为一个颜色,问你最少需要用多少次操作才能将整棵树变成一种颜色。

emmm,缩点应该可以想到,那么缩点之后我们可以观察,对于每个点,他们的周围都是与其颜色互异的点,那么也就相当于:0-1-0-1-0-1-0-1-0-1…序列,那么我们可以直接选择中点变化,然后向两边扩散,那么最少所需要的次数就是其半径的长度。那么对于树形结构来讲也是一样的。所以我们只需要在缩点之后建树,然后再跑个树的直径就好了。看代码的话也挺容易理解的。

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

const int mac=2e5+10;
#define make make_pair

struct node
{
	int to,next;
}eg[mac<<1];
int color[mac],father[mac],id[mac];
int head[mac],d=0,num=0;
vector<int>g[mac],group[mac];

int finds(int x){return x==father[x]?x:father[x]=finds(father[x]);}

void add(int u,int v)
{
	eg[++num]=node{v,head[u]};
	head[u]=num;
}

int dfs(int x,int f)
{
	int d1=0,d2=0;
	for (int i=head[x]; i!=-1; i=eg[i].next){
		int v=eg[i].to;
		if (v==f) continue;
		int p=dfs(v,x)+1;
		if (p>d1) {d2=d1; d1=p;}
		else if (p>d2) {d2=p;}
	}
	d=max(d,d1+d2);
	return d1;
}

int main(int argc, char const *argv[])
{
	int n;
	scanf ("%d",&n);
	for (int i=1; i<=n; i++) 
		scanf ("%d",&color[i]);
	for (int i=1; i<=n; i++) father[i]=i;
	for (int i=1; i<n; i++){
		int u,v;
		scanf ("%d%d",&u,&v);
		if (color[u]==color[v]){
			int fu=finds(u),fv=finds(v);
			if (fu!=fv) father[fu]=fv;
		}
		else {
			g[u].push_back(v); g[v].push_back(u);
		}
	}
	int cnt=0;
	for (int i=1; i<=n; i++)
		if (father[i]==i) id[i]=++cnt;
	for (int i=1; i<=n; i++){
		id[i]=id[finds(i)];
		group[id[i]].push_back(i);
	}
	memset(head,-1,sizeof head);
	map<pair<int,int>,int>mp;
	for (int i=1; i<=cnt; i++){
		for (auto x:group[i]){
			for (auto v:g[x]){
				if (mp[make(i,id[v])]) continue;//若两个团之间已经建边了
				mp[make(i,id[v])]=mp[make(id[v],i)]=1;
				add(i,id[v]); add(id[v],i);
			}
		}
	}
	dfs(1,-1);
	printf("%d\n",(d+1)/2);
	return 0;
}

标签:734E,并查,int,Anton,tree,vertices,color,d1
来源: https://blog.51cto.com/u_15249461/2870375

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有