Time Limit: 10000MS | Memory Limit: 65536K | |
Total Submissions: 40402 | Accepted: 13171 |
Description
Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs.
Problem
Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
Input
Output
Sample Input
2 3 3 1 2 2 3 1 3 4 2 1 2 3 4
Sample Output
Scenario #1: Suspicious bugs found! Scenario #2: No suspicious bugs found!
Hint
Source
224K | 719MS |
#include <iostream> #include <cstdio> using namespace std; int father[2005]; int rea[2005]; int find(int a){ //并查集 int i = a; while(father[i] != i){ i = father[i]; } int j = a, r; if(i != j){ while(father[j] != i){ //压缩 r = father[j]; father[j] = i; j = r; } } return i; } void mix(int x, int y){ //匹配 int fx = find(x), fy = find(y); if(fx != fy) father[fx] = fy; } int main(){ int t, m, n, a, b; int fa, fb, flag = 1, ct = 0; cin >> t; while(t--){ ct++; flag = 1; cin >> m >> n; for(int i = 0; i <= m; i++){ father[i] = i; rea[i] = 0; } for(int i = 0; i < n; i++){ scanf("%d%d", &a, &b); if(flag){ fa = find(a); fb = find(b); if(fa == fb){ flag = 0; } else if(rea[fa] && rea[fb]){ // father[rea[fa]] = fb; //这样直接赋值会破坏压缩的树状数组 // father[rea[fb]] = fa; mix(rea[fa], fb); //不能直接像上面那样直接配对,要查寻到父节点在匹配 mix(rea[fb], fa); } else if(rea[fa] && rea[fb] == 0){ // father[rea[fa]] = fb; rea[fb] = fa; mix(rea[fa], fb); } else if(rea[fa] == 0 && rea[fb]){ // father[rea[fb]] = fa; rea[fa] = fb; mix(rea[fb], fa); } else if(rea[fa] == 0 && rea[fb] == 0){ rea[fa] = fb; rea[fb] = fa; } } } if(flag){ printf("Scenario #%d:\n", ct); printf("No suspicious bugs found!\n\n"); } else{ printf("Scenario #%d:\n", ct); printf("Suspicious bugs found!\n\n"); } } return 0; }
方法二:http://blog.csdn.net/i_want_to_be_a_god/article/details/38379281
大致题意为:
给定n个bugs,编号依次1、2、……n。它们之间只有雄性和雌性之分,并给定m对交配的情况,根据这m对交配的情况,判断是否有同性恋出现的情况。若有则输出“No suspicious bugs found!”否则输出“Suspicious bugs found!”;
题目意思很明确了。而且题型也很清晰,典型的循环路径并查集。分析如下:
这里令0表示雄性,1表示雌性(这里0和1只不过表示两种对立的状态,并没有具体的含义,可以理解为要么是雄性,要么是雌性)。给每一个bug初始化deep为0,即均为雄性或雌性(深度deep表示bug的相对性别关系)。现在解释一下deep如何表示性别的相对关系:
假设A匹配B,可令deep[A]=0,deep[B]=1。现在又有B与C匹配,那么deep[B]=1,deep[C]应该为0才对。这样的话,我们可以将具有关系的bug并在同一集合中,并用模2方式来循环表示bug之间的相对性别关系。
那么假设有匹配A B,这里就有两种情况了。
1)A与B已经有了关系,即在同一个关系集合中,分两种情况讨论:
这里deep表示bug之间的相对性别关系,
11)若A的深度deep与B的深度不同(即一个为0,一个为1),则说明不是同性恋,继续输入关系
12)若A的深度deep与B的深度相同(即均为0或均为1),则说明是相同性别,为同性恋关系,已可判定结果,后续只需输入关系即可,无需继续判定
2)A与B还没有关系(即不再同一关系集合中),情况要复杂一些
由于A与B还没有关系,所以到目前为止是无法断定这个关系是错误的,所以认为这个关系正确(显然)。那么接下来的问题就是:如何将这两个关系和并成一个关系,并且还bug之间的相对性别关系在合并后仍然正确?这就是本题的难点。
分析如下: 假设A 与 B 匹配,A在以X为父节点的关系中,B在以Y为父节点的关系中。我们可以推到如下:
deep[A]=a(A与父节点X的相对性别关系为a),由于B与A匹配,那么若将B并在以X为父节点的关系中,则deep[B]=(deep[A]+1)%2。而B在以Y为父节点的关系中的深度为b(即B相对Y的性别关系为b,同样Y相对B的性别关系也为b)。这样若将B并在X关系中,那么Y的深度应该为deep[Y]= ((dee[A]+1)%2+deep[b])%2;这样以后,将Y指向X。我们可以验证一下这样以后是否B与A的相别是相反的即deep[B]=(deep[A]+1)%2;
上述操作以后:deep[B]=(deep[b]+deep[Y])%2,而deep[Y]= ((dee[A]+1)%2+deep[b])%2,带入后可得deep[B]=(deep[A]+1)%2(容易证明)即关系正确。
另外本题还要注意一点:最后结果的输出注意首字母要大写,我就贡献了一次WA。
下面是代码: 180K+719MS
#include <stdio.h> #include <stdlib.h> #include <string.h> #define Max 2010 int deep[Max]; //深度关系 int set[Max]; //并查集 int Case,n,m; int find(int x){ // 查 if(set[x]==x) //若循环到父节点,返回父节点标号 return x; int temp=find(set[x]); //查找路径上一个节点 deep[x]=(deep[set[x]]+deep[x])%2; // 路径更新 set[x]=temp; //路径压缩 return temp; //返回父节点 } int main(){ scanf("%d",&Case); for(int i=1;i<=Case;i++){ scanf("%d%d",&n,&m); memset(deep,0,sizeof(deep)); //初始化为全0 for(int j=1;j<=n;j++) // 初始化为其自身 set[j]=j; bool trag=true; //设置标记为没有同性恋 int a,b; while(m--){ if(trag){ scanf("%d%d",&a,&b); int x=find(a); int y=find(b); if(x==y){ //若在同一关系集合中 if(deep[a]==deep[b]) //若性别相同,则说明是同性恋,否则不是同性恋,正常 trag=false; //置标记为false } else{ //不再同一关系集合中,则一定正确,但要正确和并 if(x<y){ // 将标号大的并向标号小的 deep[y]=((deep[a]+1)%2+deep[b])%2; //改变父节点深度 set[y]=x; //大并小 } else{ //同上 deep[x]=((deep[b]+1)%2+deep[a])%2; set[x]=y; } } } else //若已经判定是同性恋关系,则不予判断,直接输入即可 scanf("%d%d",&a,&b); } if(trag) //输出,注意首字母大小写 printf("Scenario #%d:\nNo suspicious bugs found!\n\n",i); else printf("Scenario #%d:\nSuspicious bugs found!\n\n",i); } return 0; }