BestCoder Round #68 (div.2) 1002 tree

题意:给你一个图,每条边权值0或1,问每个点周围最近的点有多少个?

思路:并查集找权值为0的点构成的连通块。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<math.h>
 5 #include<algorithm>
 6 #define clc(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 int pre[100010],a[100010];//标记根节点
 9 int find(int x)//查找根节点
10 {
11     int r=x;
12     while(pre[r]!=r)//返回根节点r
13         r=pre[r];
14     int i=x,j;
15     while(i!=r)//路径压缩
16     {
17         j=pre[i];//在改变上级之前用临时变量j记录下他的值
18         pre[i]=r;//把上级改为根节点
19         i=j;
20     }
21     return r;
22 }
23 void join(int x,int y)//判断x,y是否连通.如果已经连通,就不用管了;如果不连通,就把它们所在的连通分支合并起
24 {
25     int fx=find(x),fy=find(y);
26     if(fx!=fy) pre[fy]=fx;
27 }
28 int main()
29 {
30     //freopen("in.txt","r",stdin);
31     int t,n,x,y,z;
32     while(~scanf("%d",&t))
33     {
34         for(int i=0; i<t; i++)
35         {
36             clc(a,0);
37             scanf("%d",&n);
38             for(int i=1; i<=n; i++)
39             {
40                 pre[i]=i;
41             }
42             for(int i=1; i<n; i++)
43             {
44                 scanf("%d%d%d",&x,&y,&z);
45                 if(!z) join(x,y);
46             }
47             for(int i=1; i<=n; i++)
48             {
49                 a[find(i)]++;
50             }
51             long long ans=0;
52             for(int i=1; i<=n; i++)
53             {
54                 int p=a[find(i)];
55                 if(p) ans^=p;
56                 else ans^=1;
57             }
58             printf("%I64d\n",ans);
59         }
60     }
61     return 0;
62 }
View Code

 

posted @ 2016-01-02 21:26  yyblues  阅读(197)  评论(0编辑  收藏  举报