pku1182 并查集 (偏移量处理)

题目链接:食物链

中文题目,题意很好理解。类似于poj2492 A Bug's Life 

在这里动物只有3种A,B,C,如果A吃B,我们可以将A对B的偏移量定为1。这题关键在于用一个数组记录每个点相对于根节点的偏移量,在合并两个集合的时候,注意保持当前两个节点的偏移量差为1, 在路径压缩过程中,依然采用递归形式,将路径上的偏移量层层改变,如果A和B偏移量之差为1, A吃B;如果为0, 表示为同类。关键在于找到修改偏移量的公式。做了2429,我感觉这题也很水!

 

代码
   
     
#include < stdio.h >
#include
< stdlib.h >
#define NN 50004
int ans;
int bin[NN], rank[NN];
int offset[NN];

int Find( int x){
if (x != bin[x]){
int t = Find(bin[x]);
offset[x]
= (offset[bin[x]] + offset[x]) % 3 ;
return bin[x] = t;
}
return x;
}
void Merge( int d, int x, int y){

int fx, fy;
fx
= Find(x);
fy
= Find(y);

if (fx == fy){
if (d == 1 ){
if (offset[x] != offset[y]){
ans
++ ;
}
}
else {
if ((offset[x] - offset[y] + 3 ) % 3 != 1 ){
ans
++ ;
}
}
}
else {
if (d == 1 ){
bin[fx]
= fy;
offset[fx]
= (offset[y] - offset[x] + 3 ) % 3 ;
}
else {
bin[fx]
= fy;
offset[fx]
= (offset[y] + 4 - offset[x]) % 3 ;
}
}
}
int main()
{
int K, X, Y, D, i, N;
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
scanf( " %d%d " , & N, & K);

for (i = 1 ; i <= N; i ++ ){
bin[i]
= i;
rank[i]
= 0 ;
offset[i]
= 0 ;
}
while (K -- ){
scanf(
" %d%d%d " , & D, & X, & Y);
if ((D == 2 && X == Y) || X > N || Y > N){
ans
++ ;
continue ;
}
Merge(D, X, Y);
}
printf(
" %d\n " , ans);

// system("pause");
return 0 ;
}

 

这题我怕麻烦就没有按秩合并,不过也过了! 呵呵

你可能感兴趣的:(并查集)