题目链接:http://172.16.200.33/JudgeOnline/problem.php?id=1003
分析:
(1)题意很简单,就是检查一堆数据中是否有同性恋,找出主要矛盾是如果1喜欢2,2喜欢3,而1又喜欢3,则矛盾。找出出现类的的矛盾
(2)这里用bugs数组存储其父亲节点的下标,用sex数组存储该虫子与根节点之间的关系。1为同性,0为异性。
(3)并查集详见注释(借鉴大神的思路,很好)
#include#include #include #include #include using namespace std;#define M 2005int sex[M],bugs[M];void init(int n) //初始化{ for(int i=0;i<=n;i++) { bugs[i]=i; sex[i]=1; }}int find(int bug) //打根{ if(bugs[bug]==bug) return bug; int temp=bugs[bug];//递归更新域,返回最终的父亲节点,把所有的孩子都更新了 //注意这里,求当前位置和父亲的关系,记录之前父亲的位置为tem,然后因为是递归, //此时的sex[temp]已经在递归中更新过了,也就是孩子和父亲的关系+父亲和爷爷的关系+1然后模2就得到 //孩子和爷爷的关系,这里用0和1表示,0表示不同性别,1表示相同性别 bugs[bug]=find(bugs[bug]); sex[bug]=(sex[bug]+sex[temp]+1)%2; return bugs[bug];}void union_set(int a,int b,int x,int y){ //合并,让前边的集合的根指向后边集合的根,成为一个集合 bugs[x]=y;//更新前边集合根和新的集合根之间的关系, //注意这里,sex[a]+sex[x]与sex[b] //相对于新的父节点必须相差1个等级,因为他们不是gay sex[x]=(sex[b]-sex[a])%2;}int main(){ int n,m,t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { if(ca>=2) printf("\n"); scanf("%d %d",&n,&m); init(n);//初始化,使其父节点为自己 bool f=false;//false:无同性恋,true:有同性恋 for(int i=1;i<=m;i++) { int bug1,bug2; scanf("%d %d",&bug1,&bug2); if(f) continue; int par1=find(bug1); int par2=find(bug2); if(par1==par2&&sex[par1]==sex[par2]) f=true; //同性 union_set(bug1,bug2,par1,par2); } if(f) printf("Scenario #%d:\nSuspicious bugs found!\n",ca); else printf("Scenario #%d:\nNo suspicious bugs found!\n",ca); } return 0;}