您的位置:首页 > Web前端

HDU-1829-A Bug's Life

2017-12-22 12:25 489 查看

A Bug's Life

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17337    Accepted Submission(s): 5553


[align=left]Problem Description[/align]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.
 
[align=left]Input[/align]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. 
[align=left]Output[/align]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. 
[align=left]Sample Input[/align]
2
3 3
1 2
2 3
1 3
4 2
1 2
3 4 
[align=left]Sample Output[/align]
Scenario #1:
Suspicious bugs found!

Scenario #2:
No suspicious bugs found!

HintHuge input,scanf is recommended.

HDU-1829-A Bug's Life

思路:
一,将所有的元素当做一个图来搜索,用一个的数组d[]来做标记是否搜索过,以及用于区分同异性,{0,1,2}
0表示未被搜索,1,2用于区分雄雌两个集合。从首遍历一遍,如果有矛盾的则为假。
code 1:
#include<iostream>
#include<cstring>
using namespace std;

const int MAX_N=2005;
int T,n,m;
bool G[MAX_N][MAX_N];
int d[MAX_N];

bool DFS(int k);
int main()
{
ios::sync_with_stdio(false);

cin>>T;
for(int T=1;T<=T;++T)
{
bool boo=true;
memset(G,0,sizeof(G));
memset(d,0,sizeof(d));
cin>>n>>m;
int a,b;
for(int i=0;i<m;++i)
{
cin>>a>>b;
if(a==b) boo=false;
G[a][b]=G[b][a]=true;
}
for(int i=1;i<=n&&boo;++i)
if(!d[i]){
d[i]=1;
if(DFS(i)==false) boo=false;
}
cout<<"Scenario #"<<T<<":"<<endl;
if(boo==true) cout<<"No suspicious bugs found!"<<endl;
else cout<<"Suspicious bugs found!"<<endl;
cout<<endl;
}
return 0;
}

bool DFS(int k)
{
bool bo=true;
int p=(d[k]==1)?2:1;
for(int i=1;i<=n&&bo;++i)
if(G[k][i]==true){
if(!d[i]){
d[i]=p;
if(DFS(i)==false){
bo=false;
}
}else if(i!=k&&d[i]!=p)
bo=false;
}
return bo;
}

二,并查集,用一个数组存元素的关联元素,将性别相同的放在一个集合里,若关联元素在同一集合则有Bug,否则将性别相同的集合合并。
code 2:
#include<iostream>
#include<algorithm>
using namespace std;

const int MAX_N = 10005; /*结点数目上限*/
int id[MAX_N]; /*id[x]表示x的父节点*/
int Rank[MAX_N]; /*Rank[x]是x的深度的一个上界*/
int d[MAX_N]; // 与i性别相反的虫子号

int Find(int x);
void Union(int x, int y);
int main()
{
// ios::sync_with_stdio(false);

int T,m,n,k=1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++){
id[i] = i; Rank[i]=d[i]=0;
}
int a,b,flag=1;
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(!flag) continue;
if(Find(a)==Find(b)){ //判断两个虫子在不在同一个集合
flag=0; continue;
}
if(d[a]==0) d[a]=b;
else Union(d[a],b);
if(d[b]==0) d[b]=a;
else Union(d[b],a);
}
if(flag) printf("Scenario #%d:\nNo suspicious bugs found!\n",k++);
else printf("Scenario #%d:\nSuspicious bugs found!\n",k++);
printf("\n");
}
return 0;
}

int Find(int x)
{
if(id[x] != x){
id[x] = Find(id[x]);
}
return id[x];
}

/*按秩合并x,y所在的集合*/
void Union(int x, int y)
{
int fx = Find(x);
int fy = Find(y);
if(Rank[fx] > Rank[fy]){/*让Rank比较高的作为父结点*/
id[fy] = fx;
}else{
id[fx] = fy;
if(Rank[fx] == Rank[fy]) Rank[fy]++;
}
}三,若a,b存在恋爱关系,则a+n,b+n分别表示与a,b异性,则将a,b+n放在一组,b,a+n放在一组,匹配时,若a,b在同一组,则说明有 bug
code 3:#include<iostream>
using namespace std;
typedef long long LL;

int T;
LL k=1,n,m,f[4050];

int find(int x)
{
if(f[x] == x) return x;
return find(f[x]);
}

void Union(int x, int y)
{
int a = find(x);
int b = find(y);
if(a != b)
f[a] = b;
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

cin>>T;

while(k<=T)
{
cin>>n>>m;
bool flag = true;
for(int i=0; i<=2*n; i++)
f[i] = i;

int a,b;
for(int i=0; i<m; i++)
{
cin>>a>>b;

if(!flag) continue;
if(find(a) != find(b))
{
Union(a+n,b);
Union(a,b+n);
}
else{
flag = false;
}

}

cout<<"Scenario #"<<k<<":"<<endl;
if(flag) cout<<"No suspicious bugs found!"<<endl;
else cout<<"Suspicious bugs found!"<<endl;
cout<<endl;
k++;
}

return 0;
}

四,带权并查集,用一个集合
struct node{
int k; //父子关系:0 1 
int p; //父亲节点编号 
}id[MAX_N];     
表示元素,其中 k表示父子关系,0表示同性,1表示异性;p为父母编号。
容易推出,儿子 i 与父亲的父亲的关系为 (id[i].k+id[id[i].p].k)%2; 
集合合并时,两集合根节点的关系为 fa=Find(a);id[fa].k=(id[b].k+1+id[a].k)%2;
在处理每对元素时,若他们在同一集合则又他们间的关系为 1(异性),在通过两者与根节点的关系可判断
若(id[a].k+id[b].k)%2==0 则他们间有bug. 若不在同一集合则合并为一个集合。
code 4:
#include<iostream>
#include<cstring>
using namespace std;

const int MAX_N=2005;
struct node{
int k; //父子关系:0 1
int p; //父亲节点编号
}id[MAX_N];
int T,n,m;

int Find(int x);
void Union(int a,int b);
int main()
{
ios::sync_with_stdio(false);

cin>>T;
for(int T=1;T<=T;++T)
{
bool boo=true;
memset(id,0,sizeof(id));
cin>>n>>m;
int a,b;
for(int i=1;i<=n;++i)
{
id[i].p=i; id[i].k=0;
}
for(int i=0;i<m;++i)
{
cin>>a>>b;
if(boo==false) continue;
if(a==b) boo=false;
if(Find(a)==Find(b)&&(id[a].k+id[b].k)%2==0){
boo=false;
}else Union(a,b);
}

cout<<"Scenario #"<<T<<":"<<endl;
if(boo==true) cout<<"No suspicious bugs found!"<<endl;
else cout<<"Suspicious bugs found!"<<endl;
cout<<endl;
}
return 0;
}

int Find(int x)
{
int p=id[x].p;
if(id[x].p!=x){
id[x].p=Find(id[x].p);
id[x].k=(id[x].k+id[p].k)%2;
}
return id[x].p;
}

void Union(int a,int b)
{
int fa=Find(a),fb=Find(b);
id[fa].p=fb;
id[fa].k=(id[b].k+1+id[a].k)%2;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: