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 contains
n
points and
n−1
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 contain
i
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.
T≤50,n≤105,u,v∈[1,n],w∈[0,1]
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.
T≤50,n≤105,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 .
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
1 3 1 2 0 2 3 1
Sample Output
1 in 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);
}
}