题目链接: 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 }
时间: 2024-12-11 10:58:22