poj2492(种类并查集)
Posted ygeloutingyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于poj2492(种类并查集)的主要内容,如果未能解决你的问题,请参考以下文章