题意:给你一个图,每条边权值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 }
时间: 2024-10-07 06:07:55