题意:一棵树中n个节点被染上了c[i]颜色,让你在一棵树中随便选一个节点作为根节点,然后把整棵树抬起来,问你是否存在一个节点,使得以这个点为根节点的所有子树中的节点的颜色相同
解题思路:若有这样的节点,边的两端端点颜色不一样的边(设为特殊边,这样的边总数为m)肯定是有和根节点连在一起的(如果没有和根节点相连的话,肯定会造成子树里面有两个颜色不一样的);
int main()
{
while(~scanf("%d",&n))
{
k=-1;
memset(x,0,sizeof x);
for(int i=1;i<n;i++)
scanf("%d %d",&u[i],&v[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
int sum=0;
for(int i=1;i<n;i++)
{
if(c[u[i]]!=c[v[i]])
{
sum++;
x[u[i]]++,x[v[i]]++;
}
}
for(int i=1;i<=n;i++)
{
if(sum==x[i])
{
k=i;break;
}
}
if(k==-1) printf("NO\n");
else printf("YES\n%d\n",k);
}
return 0;
}
another thought http://blog.csdn.net/black_miracle/article/details/54839354
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
int to,nex,num;
}edge[200005];
int cnt,head[100005],num[100005],ans,vis[100005],lab,sol[100005];
void add(int u,int v){
edge[cnt].to=v;
edge[cnt].nex=head[u];
head[u]=cnt++;
}
void dfs(int t,int pre){
int ss=num[t];
for(int i=head[t];~i;i=edge[i].nex){
int v=edge[i].to;
if(vis[v])continue;
vis[v]=1;
if(pre==0)ss=num[v];//如果是根节点
else{
if(pre!=num[v]){//如果不相等,就说明变数字
ans++;
lab=t;//lab记录下一次搜的位置
return ;
}
}
dfs(v,ss);
}
}
void solve(int t){
if(sol[t]){//防止死循环
printf("NO\n");
return ;
}
sol[t]++;
ans=0;
memset(vis,0,sizeof(vis));
vis[t]=1;
dfs(t,0);
if(ans>=2){
printf("NO\n");
}
else if(ans==1){
solve(lab);
}
else{
printf("YES\n%d\n",t);
}
}
int main(){
int x,y,n,i,j;
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(i=1;i<=n;i++)scanf("%d",&num[i]);
solve(1);
return 0;
}