杭电OJ tree(并查集)

来源:互联网 发布:淘货源软件下载 编辑:程序博客网 时间:2024/06/16 20:34

tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 386    Accepted Submission(s): 190


Problem Description
There is a tree(the tree is a connected graph which containsn points and n1 edges),the points are labeled from 1 to n,which edge has a weight from 0 to 1,for every point i[1,n],you should find the number of the points which are closest to it,the clostest points can containi itself.
 


Input
the first line contains a number T,means T test cases.

for each test case,the first line is a nubmer n,means the number of the points,next n-1 lines,each line contains three numbers u,v,w,which shows an edge and its weight.

T50,n105,u,v[1,n],w[0,1]
 


Output
for each test case,you need to print the answer to each point.

in consideration of the large output,imagine ansi is the answer to point i,you only need to output,ans1 xor ans2 xor ans3.. ansn.
 


Sample Input
131 2 02 3 1
 


Sample Output
1in the sample.$ans_1=2$$ans_2=2$$ans_3=1$$2~xor~2~xor~1=1$,so you need to output 1.

连通路径,并查集应用。

bestcoder比赛的时候,一直以为0是表示没有路,而1表示有路,最近的当然是1的那条边咯~。然后就是经验不足带来的无限WA的后果。很忧伤,很忧伤。。。。。。。。。。

这里大概题意是这样的:0边权和1边权都表示有路,但是0当然比1近,所以我们这里只考虑0的路,并不考虑1的路,因为我们要找的是当前点能找到的近的点。如果我要从这个点向周围找点,因为0边权进,所以我会去放弃1边权的点。所以这里当边权为0的时候,连通两点,直接不考虑1的路。

        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            f[i]=i;            j[i]=1;//集合数。        }        for(int i=0;i<n-1;i++)        {            int x,y,c;            scanf("%d%d%d",&x,&y,&c);            if(c==0)            merge(x,y);        }

然后我们这里就要涉及一个找到点的个数的问题。我们这里用一个数组j表示。

 当连通两点的时候,一个集合的点的数量,给另一个集合。

int find(int x){    return f[x]==x?x:(f[x] = find(f[x]));}void merge(int a,int b){    int A,B;    A=find(a);    B=find(b);    if(A!=B)    {        f[A]=B;//这里表示A集合给了B(也可能是点)        j[B]+=j[A];//然后把A集合的数量也加到B上、    }}


然后最后每一个点都找到自己的祖宗,询问有多少个点距离自己都是0.然后每一个都xor一下就可以了~。

最后上完整的AC代码:

#include<stdio.h>#include<string.h>using namespace std;int f[100010];int j[100010];int find(int x){    return f[x]==x?x:(f[x] = find(f[x]));}void merge(int a,int b){    int A,B;    A=find(a);    B=find(b);    if(A!=B)    {        f[A]=B;        j[B]+=j[A];    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            f[i]=i;            j[i]=1;        }        for(int i=0;i<n-1;i++)        {            int x,y,c;            scanf("%d%d%d",&x,&y,&c);            if(c==0)            merge(x,y);        }        int output=j[find(1)];        for(int i=2;i<=n;i++)        {            output^=j[find(i)];        }        printf("%d\n",output);    }}






























0 0