题目大意:输入一个数t,表示测试组数。然后每组第一行两个数字n,m,n表示有n只昆虫,编号从1—n,m表示下面要输入m行交配情况,每行两个整数,表示这两个编号的昆虫为异性,要交配。要求统计交配过程中是否出现冲突,即是否有两个同性的昆虫发生交配。
思路:并查集,和1703几乎一样的思路。
#include <iostream>
using namespace std;
#include <memory.h>
#include <stdio.h>
// Model 1
const int MAXSIZE = 2010;
int rank[MAXSIZE];//rank[x]表示x的秩
int parent[MAXSIZE];
int n;//集合元素,从1到n
int m;
int opposite[MAXSIZE];
/* 查找x元素所在的集合,回溯时压缩路径*/
int FindSet(int x) {
if (x!=parent[x])
parent[x]=FindSet(parent[x]);
return parent[x];
}
//Union按秩合并,即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小
//通过秩rank的大小来衡量元素的多少
void Union(int root1, int root2) {
int x=FindSet(root1),y=FindSet(root2);
if (x==y)
return;
if (rank[x]>rank[y])
parent[y]=x;
else {
parent[x]=y;
if (rank[x]==rank[y])
++rank[y];
}
}
void Initialization() {
int i;
memset(rank,0,sizeof(rank));
memset(opposite,0,sizeof(opposite));
for (i=1;i<=n;i++)
parent[i]=i;
}
int main()
{
int case_num,case_ctr,i,j;
int flag;
int x,y;
scanf("%d",&case_num);
for (case_ctr=1;case_ctr<=case_num;case_ctr++) {
flag=1;
scanf("%d%d",&n,&m);
Initialization();
for (i=0;i<m;i++) {
scanf("%d%d",&x,&y);
if (flag==1) {
if (FindSet(x)==FindSet(y))
flag=0;
if (opposite[x]==0&&opposite[y]==0) {
opposite[x]=y;
opposite[y]=x;
}
else if (opposite[x]==0) {
opposite[x]=y;
Union(x,opposite[y]);
}
else if (opposite[y]==0) {
opposite[y]=x;
Union(y,opposite[x]);
}
else {
Union(x,opposite[y]);
Union(y,opposite[x]);
}
}
}
printf("Scenario #%d:\n",case_ctr);
if (flag==1)
printf("No suspicious bugs found!\n");
else
printf("Suspicious bugs found!\n");
printf("\n");
}
return 0;
}