HDU 5606 tree 并查集

题意:有一个生成树,对于每一个点定义一个值k,表示所有的点到这个点的距离为零的个数,求出所有点的结果,然后异或之。


想法:文中的closest,最近,显然就是距离要为零,因为本身永远是零,只有到该点的距离是零的点,才可以。将每条边权为0的u,v点用并查集合并,用Rank记录一个祖先下加上自己和自己的孩子数,然后结果异或即可。


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int nodes=100000+50;
const int edges=100000+50;
int n,father[nodes],Rank[nodes];
struct node
{
    int u,v;
    double w;
}e[edges];
int ans[nodes];
void Init()
{
	for(int i=1;i<=n;i++)
	{
		father[i]=i;
		Rank[i]=1;
	}
}
int find(int x)
{
	if(x!=father[x])
	father[x]=find(father[x]);
	return father[x];
}
void union_set(int a,int b)
{
	a=find(a);
	b=find(b);
	if(a==b) return;
	if(Rank[a]>Rank[b])
	{
		father[b]=a;
		Rank[a]+=Rank[b];
	}
	else 
	{
		father[a]=b;
		Rank[b]+=Rank[a];
	}
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        Init();
        for(int i=1;i<=n-1;i++)
        {
            scanf("%d%d%lf",&e[i].u,&e[i].v,&e[i].w);
        }
        for(int i=1;i<=n;i++)
        {
            if(e[i].w==0)
            union_set(e[i].u,e[i].v);
        }
        int res=0;
        for(int i=1;i<=n;i++)
        {
            int z=find(i);
            res^=Rank[z];
        }
        printf("%d\n",res);
    }
    return 0;
}

你可能感兴趣的:(HDU 5606 tree 并查集)