有一個樹(n個點, n−1條邊的聯通圖),點標號從1~n,樹
的邊權是0或1.求離每個點最近的點個數(包括自己).
輸入描述
第一行一個數字T,表示T組數據.
對於每組數據,第一行是一個n,表示點個數,接下來n
−1,每行三個整數u,v,w,表示一條邊連接的兩個點和邊
權.
T=50,1≤n≤100000,1≤u,v≤n,0≤w≤1
輸出描述
對於每組數據,輸出答案.
考慮到輸出規模過大,設ansi表示第i個點的答案.你只
需輸出ans1 xor ans2 xor ans3.. xor ansn即可.
輸入樣例
1
3
1 2 0
2 3 1
輸出樣例
1
Hint
ans1=2
ans2=2
ans3=1
2 xor 2 xor 1 = 1, 因此輸出1.
首先因爲求的是距離最近的點的個數,自己與自己的距離爲0,
所以當前只有可能到某個點的距離爲0,距離纔是最近的,所以
就是求每個點所在連通塊的個數。
找點的時候注意要查找父節點的個數,因爲更新的是父節點的值。
#include <stdio.h>
#define LL long long
const int maxn = 100005;
int father[maxn];
int cnt[maxn];
void init ( int n )
{
for ( int i = 1; i <= n; i ++ )
father[i] = i, cnt[i] = 1;
}
int find ( int x )
{
int r = x;
while ( father[r] != r )
r = father[r];
int i = x;
while ( i != r )
{
int j = father[i];
father[i] = r;
i = j;
}
return r;
}
void merge ( int x, int y )
{
int fx = find ( x ), fy = find ( y );
if ( fx != fy )
{
father[fx] = fy;
cnt[fy] += cnt[fx]; //就算賦值也沒用,只有父節點會實時更新
}
}
int main ( )
{
int T, n, u, v, w;
scanf ( "%d", &T );
while ( T -- )
{
scanf ( "%d", &n );
init ( n );
for ( int i = 0; i < n-1; i ++ )
{
scanf ( "%d%d%d", &u, &v, &w );
if ( w == 0 ) //權值爲0就合併
merge ( u, v );
}
int ans = 0;
for ( int i = 1; i <= n; i ++ )
ans ^= cnt[ find ( i ) ]; //連通塊大小
printf ( "%I64d\n", ans );
}
return 0;
}