A Bug's Life
并查集的应用。与食物链那到题目类似,对于关系明确的bug之间合并,用数组p[x]和d[x]分别表示x的父节点以及x与父节点之间的关系,我们可以假设d[x]=0表示x与p[x]是同性,d[x]= 1表示x与p[x]是异性。对于查操作的时候,我们不断的压缩路径,同时更新d[x]的值,这里d[x] = (d[x] + d[p[x]])%2,很容易推出来,具体看程序中find_x()函数。然后是合并操作,对于给定的x和y,我们先找到其根节点,然后合并根节点,这里画一下就能得出结论:d[ty] = (d[x] + 1 - d[y])%2,其中ty=find_x(y).具体看程序。本题需要注意的是:在读入数据的时候,要把每一组所对应的数据全部读完,并不能因为找到一组同性关系就退出。
/*
author : csuchenan
LANG : c++
algorithm: disjointset data structure
*/
#include <cstdio>
#include <cstring>
#define maxn 2005
int p[maxn] ;
short d[maxn];
int N ;
int M ;
void init(){
for(int i = 1 ; i <= N ; i ++){
p[i] = i ;
d[i] = 0 ;
}
}
int find_x(int x){
if(p[x] == x)
return x ;
int tx( find_x( p[x] ) ) ;
d[x] = (d[x] + d[ p[x] ])%2 ;
p[x] = tx ;
return tx ;
}
void join(int x , int y){
int tx = find_x(x) ;
int ty = find_x(y) ;
if(tx==ty)
return ;
d[ty] = (d[x] + 1 - d[y])%2 ;
p[ty] = tx ;
return ;
}
bool solve(){
int x ;
int y ;
bool flag ;
flag = 0 ;
for(int k = 0 ; k < M ; k ++){
scanf("%d%d" , &x , &y) ;
if(!flag){
int tx = find_x(x) ;
int ty = find_x(y) ;
if(tx == ty && (d[x] + d[y])%2==0){
flag = 1 ;
}
join(x , y) ;
}
}
return flag ;
}
int main(){
int T ;
int t(0) ;
scanf("%d" , &T) ;
while(t < T){
scanf("%d%d" , &N , &M) ;
init() ;
printf("Scenario #%d:\n" , ++t ) ;
if( solve() )
printf("Suspicious bugs found!\n") ;
else
printf("No suspicious bugs found!\n") ;
printf("\n") ;
}
return 0 ;
}
POJ 1703 Find them, Catch them
这个题目和POJ2492相同,关系也是2元关系(由于只有两个gang),采用相同的办法,这里是查询x和y是不是在同一个gang里面,首先如果x和y的父节点是不同的,那么x与y之间的关系肯定不确定,然后如果父节点相同,那么如果d[x]与d[y]是相同的,或者(d[x]+d[y])%2==0,则说明x和y肯定在同一个gang里面,否则肯定在不同的gang里。
/*
author:csuchenan
LANG: c++
Algorithm: disjointset data structure
*/
#include <cstdio>
#include <cstring>
#define maxn 100005
int p[maxn] ;
short d[maxn] ;
int N , M ;
void init(){
for(int i = 1 ; i <= N ; i ++){
p[i] = i ;
d[i] = 0 ;
}
}
int find_x(int x){
if(x==p[x])
return x ;
int tx = find_x(p[x]) ;
d[x] = (d[x] + d[ p[x] ])%2 ;
p[x] = tx ;
return tx ;
}
void join(int x , int y){
int tx = find_x(x) ;
int ty = find_x(y) ;
if(tx==ty)
return ;
d[ty] = (d[x] + 1 - d[y])%2 ;
p[ty] = tx ;
}
void solve(){
char c ;
int x ;
int y ;
for(int i = 0 ; i < M ; i++){
getchar() ;
scanf("%c%d%d" , &c , &x , &y) ;
int tx = find_x(x) ;
int ty = find_x(y) ;
if(c=='A'){
if(tx!=ty)
printf("Not sure yet.\n") ;
else if( (d[x] + d[y])%2==0 )
printf("In the same gang.\n") ;
else
printf("In different gangs.\n") ;
}
else
join(x , y) ;
}
}
int main(){
int T ;
scanf("%d" , &T) ;
while(T--){
scanf("%d%d" , &N , &M) ;
init() ;
solve() ;
}
return 0 ;
}