首页 > 学院 > 开发设计 > 正文

CodeForces 763A Timofey and a tree

2019-11-11 07:49:29
字体:
来源:转载
供稿:网友

A. Timofey and a treetime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard output

Each New Year Timofey and his friends cut down a tree of n vertices and bring it home. After that they paint all the n its vertices, so that the i-th vertex gets color ci.

Now it's time for Timofey birthday, and his mother asked him to remove the tree. Timofey removes the tree in the following way: he takes some vertex in hands, while all the other vertices move down so that the tree becomes rooted at the chosen vertex. After that Timofey brings the tree to a trash can.

Timofey doesn't like it when many colors are mixing together. A subtree annoys him if there are vertices of different color in it. Timofey wants to find a vertex which he should take in hands so that there are no subtrees that annoy him. He doesn't consider the whole tree as a subtree since he can't see the color of the root vertex.

A subtree of some vertex is a subgraph containing that vertex and all its descendants.

Your task is to determine if there is a vertex, taking which in hands Timofey wouldn't be annoyed.

Input

The first line contains single integer n (2 ≤ n ≤ 105) — the number of vertices in the tree.

Each of the next n - 1 lines contains two integers u and v (1 ≤ u, v ≤ nu ≠ v), denoting there is an edge between vertices u and v. It is guaranteed that the given graph is a tree.

The next line contains n integers c1, c2, ..., cn (1 ≤ ci ≤ 105), denoting the colors of the vertices.

Output

PRint "NO" in a single line, if Timofey can't take the tree in such a way that it doesn't annoy him.

Otherwise print "YES" in the first line. In the second line print the index of the vertex which Timofey should take in hands. If there are multiple answers, print any of them.

Examplesinput
41 22 33 41 2 1 1output
YES2input
31 22 31 2 3output
YES2input
41 22 33 41 2 1 2output
NO

题意:简述就是说给我们一个树:树中有n个节点,每个节点都会有一个颜色。(用1~n之间不同的数字表示。)同时还说明了树中各个节点之间的关系。(用n-1个u,v表示。)现在问我们以哪个节点作为根,可以使得这个根下的所有子树都为纯色。(子树中的所有节点的颜色都相同。)如果有输出那个节点,如果存在多个答案只需输出任意解。如果没有就输出“NO”。

思路:这个题应该至少有两种解法。第一种是假设一个点为根然后用dfs遍历一遍它的子树,并且判断这个子树是否可以为根就行了。(但是,这种做法写的不好容易超时。而且代码实现也比较麻烦,需要先用邻接表存储整个树才行。)第二种是在直接使用结构体存储n-1对输入,然后在输入完颜色之后遍历一遍数组记录下每个节点与它相邻的节点中不同色的数量cnt[i](对于第i个节点有cnt[i]个相邻节点与节点i的颜色不同。)以及所有相邻节点中不同色的对数m,最后在遍历数组cnt,如果存在第i个节点cnt[i]==m。则第i个节点就是那个根,如果不存在那就可以直接输出“NO”了。因为已经说明了给我们的一定是一个树,所以,这也就是第二种做法的正确的基本。

     在比赛中我原本是用第一种思路来解的,虽然当时是过了。但是,在重测时却在在60+组中超时了。虽然第二天我就把我原来的代码调完AC了。但我还是觉得那个代码又臭又长,所以,就不放出来了。(第一种思路可以在O(nlongn)时间复杂度内完成。)直接上第二个思路的代码,代码相对来说就比较精简。(第二种思路的时间复杂度是O(n)。)

代码:

#include<iostream>#include<cstring>#define MAX 100005using namespace std;struct edge{	int a,b;};edge E[MAX];//在这个结构体中用来存储输入,a,b之间相连。 int poit[MAX],cnt[MAX];//用poit数组来存储每个节点的颜色。//cnt存储与它相邻的点中颜色不同的数量。 int main(){	int n;	while(cin>>n){		int m=0;		for(int j=1;j<n;j++)			cin>>E[j].a>>E[j].b;		for(int j=1;j<=n;j++)			cin>>poit[j];		memset(cnt,0,sizeof(cnt));		for(int j=1;j<n;j++){			if(poit[E[j].a]!=poit[E[j].b]){				cnt[E[j].a]++,cnt[E[j].b]++;				m++;			}		//m表示的是总对数,因为,输入不会重复,所以m才可以直接这样计数。 		}		for(int j=1;j<=n;j++){			if(cnt[j]==m){				cout<<"YES"<<endl<<j<<endl;				goto end;			}		//如果找到了一个cin[j]==m那就找到这个根了。 		}		cout<<"NO"<<endl;		end:;	}} 

总结:  总得来说这个题还是相当好的,目测这个就是正解了。代码实现没有什么难度,只是想要想到这一点比较麻烦。即使想不到这个方法。但是,对于一些人来说也可以使用强硬的代码水平来AC。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表