poj2492(种类并查集/各种解法)

题目链接: http://poj.org/problem?id=2492

 

题意: 有t组测试数据, 对于每组数据,第一行n, m分别表示昆虫的数目和接下来m行x, y,

x, y表示教授判断x, y为异性, 问教授是否有错误判断,即存在x, y为同性;

 

这道题和poj1703类似, 不过更简单一点 (poj1703题解)

 

解法1: 我们可以用rank[x]记录x与其父亲节点的关系, rank[x]=0表同性, rank[x]=1表异性;

假设前面的教授判断都是正确的, 若后面存在与前面判断矛盾的数据,那么教授判断有误;

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define MAXN 2010
 4 using namespace std;
 5 
 6 int rank[MAXN], pre[MAXN]; //***rank[x]存储x与其父亲节点的关系
 7 
 8 int find(int x){  //***递归压缩路径
 9     if(x!=pre[x]){
10         int px=find(pre[x]);
11         rank[x]=(rank[x]+rank[pre[x]])%2;  //***跟新rank[x]
12         pre[x]=px;
13     }
14     return pre[x];
15 }
16 
17 int jion(int x, int y){
18     int px=find(x);
19     int py=find(y);
20     if(px==py){
21         if((rank[x]+rank[y])%2==0){ //**rank得出x, y的关系为同性,又由题意得出输入的x, y是异性, 矛盾
22             return 1;
23         }else{
24             return 0;
25         }
26     }else{
27         pre[py]=px; //**合并
28         rank[py]=(rank[x]+rank[y]+1)%2; //**更新rank[py]
29     }
30     return 0;
31 }
32 
33 int main(void){
34     int t, m, n;
35     scanf("%d", &t);
36     for(int k=1; k<=t; k++){
37         scanf("%d%d", &n, &m);
38         for(int i=0; i<=n; i++){
39             pre[i]=i;
40             rank[i]=0;
41         }
42         int flag=0;
43         while(m--){
44             int x, y;
45             scanf("%d%d", &x, &y);
46             if(jion(x, y)){
47                 flag=1;
48             }
49         }
50         if(flag){
51             printf("Scenario #%d:\nSuspicious bugs found!\n\n", k);
52         }else{
53             printf("Scenario #%d:\nNo suspicious bugs found!\n\n", k);
54         }
55     }
56     return 0;
57 }

 

解法2:  并查集里面合并同一性别的昆虫, 用n+x表示与x性别相反的昆虫

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define MAXN 2010
 4 using namespace std;
 5 
 6 int pre[MAXN*2];
 7 
 8 int find(int x){  //***递归压缩路径
 9     return x==pre[x]?pre[x]:pre[x]=find(pre[x]);
10 }
11 
12 void jion(int x, int y){//**合并
13     int px=find(x);
14     int py=find(y);
15     if(px!=py){
16         pre[px]=py;
17     }
18 }
19 
20 int main(void){
21     int t, m, n;
22     scanf("%d", &t);
23     for(int k=1; k<=t; k++){
24         scanf("%d%d", &n, &m);
25         for(int i=0; i<=2*n; i++){
26             pre[i]=i;
27         }
28         int flag=0;
29         while(m--){
30             int x, y;
31             scanf("%d%d", &x, &y);
32             if(find(x)==find(y)){
33                 flag=1;
34             }else{
35                 jion(x, y+n);
36                 jion(x+n, y);
37             }
38         }
39         if(flag){
40             printf("Scenario #%d:\nSuspicious bugs found!\n\n", k);
41         }else{
42             printf("Scenario #%d:\nNo suspicious bugs found!\n\n", k);
43         }
44     }
45     return 0;
46 }

 

解法3: 用vis数组标记, vis[x]存储与x性别不同的昆虫

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define MAXN 2010
 4 using namespace std;
 5 
 6 int pre[MAXN*2], vis[MAXN*2];
 7 
 8 int find(int x){  //***递归压缩路径
 9     return x==pre[x]?pre[x]:pre[x]=find(pre[x]);
10 }
11 
12 void jion(int x, int y){//***合并
13     int px=find(x);
14     int py=find(y);
15     if(px!=py){
16         pre[px]=py;
17     }
18 }
19 
20 int main(void){
21     int t, m, n;
22     scanf("%d", &t);
23     for(int k=1; k<=t; k++){
24         scanf("%d%d", &n, &m);
25         for(int i=0; i<=2*n; i++){
26             pre[i]=i;
27             vis[i]=0;
28         }
29         int flag=0;
30         while(m--){
31             int x, y;
32             scanf("%d%d", &x, &y);
33             if(find(x)==find(y)){
34                 flag=1;
35             }else if(vis[x]+vis[y]==0){ //***如果之前x, y都没有出现
36                 vis[x]=y;
37                 vis[y]=x;
38             }else if(!vis[x]){ //***x没有出现
39                 vis[x]=y;
40                 jion(x, vis[y]);
41             }else if(!vis[y]){ //***y没有出现
42                 vis[y]=x;
43                 jion(y, vis[x]);
44             }else{ //***都出现过
45                 jion(x, vis[y]);
46                 jion(vis[x], y);
47             }
48         }
49         if(flag){
50             printf("Scenario #%d:\nSuspicious bugs found!\n\n", k);
51         }else{
52             printf("Scenario #%d:\nNo suspicious bugs found!\n\n", k);
53         }
54     }
55     return 0;
56 }

 

转载于:https://www.cnblogs.com/geloutingyu/p/6117262.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值