2013
12-23

# A Bug’s Life

Background
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.

The first line of the input contains the number of scenarios. Each scenario starts with one line giving the number of bugs (at least one, and up to 2000) and the number of interactions (up to 1000000) separated by a single space. In the following lines, each interaction is given in the form of two distinct bug numbers separated by a single space. Bugs are numbered consecutively starting from one.

The output for every scenario is a line containing "Scenario #i:", where i is the number of the scenario starting at 1, followed by one line saying either "No suspicious bugs found!" if the experiment is consistent with his assumption about the bugs’ sexual behavior, or "Suspicious bugs found!" if Professor Hopper’s assumption is definitely wrong.

2
3 3
1 2
2 3
1 3
4 2
1 2
3 4

Scenario #1:
Suspicious bugs found!

Scenario #2:
No suspicious bugs found!

HintHuge input,scanf is recommended. 

思路：就是同性别的合并在一个集合中，然后每次输入看u，v是否在同一个集合中。。。然后不知道为什么用路径压缩不可以写。。。一些就TLE了。。。无语了。。。orz。。。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=2000+20;
int parent[MAXN];
int mark[MAXN];
int n,m;

void Initiate(){
memset(mark,0,sizeof(mark));
for(int i=1;i<=n;i++){
parent[i]=i;
}
}

int Find(int x){
int s=x;
while(s!=parent[s]){
s=parent[s];
}
return s;
/*
int s;
for(s=x;parent[s]>=0;s=parent[s]);
while(s!=x){
int tmp=parent[x];
parent[x]=s;
x=tmp;
}
return s;
*/
}

void Union(int R1,int R2){
int r1=Find(R1);
int r2=Find(R2);
if(r1<r2){
parent[r2]=r1;
}else
parent[r1]=r2;
}

int main(){
int _case,t=1;
scanf("%d",&_case);
while(_case--){
scanf("%d%d",&n,&m);
Initiate();
bool flag=true;
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(!flag)continue;
if(Find(u)==Find(v)){
//找到同性的了。。。
flag=false;
continue;
}else {
if(mark[u]==0)mark[u]=v;
else Union(mark[u],v);//同性的并入一个集合
if(mark[v]==0)mark[v]=u;
else Union(mark[v],u);
}
}
printf("Scenario #%d:\n",t++);
if(!flag){
printf("Suspicious bugs found!\n");
}else {
printf("No suspicious bugs found!\n");
}
puts("");
}
return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=10000000+100;
int parent[MAXN];
int _count[MAXN];
int n;
int MAX;

void Initiate(){
for(int i=1;i<MAXN;i++){
parent[i]=-1;
_count[i]=1;
}
}

int Find(int x){
int s;
for(s=x;parent[s]>=0;s=parent[s]);
while(s!=x){
int tmp=parent[x];
parent[x]=s;
x=tmp;
}
return s;
}

void Union(int R1,int R2){
int r1=Find(R1);
int r2=Find(R2);
if(r1!=r2){
parent[r2]=r1;
_count[r1]+=_count[r2];
}
}

int main(){
while(~scanf("%d",&n)){
Initiate();
MAX=0;
for(int i=1;i<=n;i++){
int u,v;
scanf("%d%d",&u,&v);
Union(u,v);
}
for(int i=1;i<MAXN;i++){
if(parent[i]==-1&&_count[i]>MAX){
MAX=_count[i];
}
}
printf("%d\n",MAX);
}
return 0;
}

1. 我还有个问题想请教一下，就是感觉对于新手来说，递归理解起来有些困难，不知有没有什么好的方法或者什么好的建议？

2. 如果两个序列的最后字符不匹配（即X [M-1]！= Y [N-1]）
L（X [0 .. M-1]，Y [0 .. N-1]）= MAX（L（X [0 .. M-2]，Y [0 .. N-1]），L（X [0 .. M-1]，Y [0 .. N-1]）
这里写错了吧。