您的位置:首页 > Web前端

poj 2492 A Bug's Life

2013-04-27 15:14 323 查看
[align=center]A Bug's Life[/align]

Time Limit: 10000MSMemory Limit: 65536K
Total Submissions: 23591Accepted: 7674
Description
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.
Input
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.
Output
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.
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
Huge input,scanf is recommended.

题意:给出没对发生关系的虫子,判断是否存在同性之间发生关系。
思路:用一个r[i]数组记录与i发生关系的另一方,例如:s和t交配过,则r[s]=t,r[t]=s,对于下一对虫子a、b,判断将a和b联合到哪一个集合中取决于a或b曾经与哪一个虫子交配过,所以a和r[b]联合,b和r[a]联合。

AC代码:
#include <cstdio>
#include <cstring>
#define N 2005
using namespace std;

int father
,r
,rank
;
int Find_set(int n)
{
if(n!=father
)
father
=Find_set(father
);         //路径压缩技术,使f[i]直接指向最新的根节点
return father
;
}
void Union(int a,int b)                  //按秩合并,防止产生退化的树
{
int ra=Find_set(a);
int rb=Find_set(b);
if(rank[ra]>rank[rb])
father[rb]=ra;
else
{
if(rank[ra]==rank[rb]) rank[rb]++;
father[ra]=rb;
}
}
int main()
{
int n,m,x,t,y,c=0;;
scanf("%d",&t);
while(t--)
{
c++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
father[i]=i;
r[i]=0;
rank[i]=0;
}
int flag=0;
while(m--)
{
scanf("%d%d",&x,&y);
if(!flag)
{
if(Find_set(x)==Find_set(y)) flag=1;        //若x和y的祖先相同,x和y处于同一集合中
else
{
if(r[x]!=0) Union(r[x],y);                 //若x曾经交配过,则将r[x]和y联合
else if(r[y]!=0) Union(r[y],x);            //若y曾经交配过,则讲r[y]和x联合
else                                      //x和y都没有交配过,则令x和y互指
{
r[x]=y;
r[y]=x;
}
}
}
}
printf("Scenario #%d:\n",c);
if(flag)
printf("Suspicious bugs found!\n\n");
else
printf("No suspicious bugs found!\n\n");
}
return 0;
}

法二:
与poj1182食物链思路一样,详细请看食物链的题解
AC代码:
#include <cstdio>
#include <cstring>
#define N 50005
using namespace std;

int father
,rank
;         //rank[i]表示i到根节点的偏移量
int Find_set(int n)
{
int temp;
if(n==father
) return n;
temp=father
;
father
=Find_set(father
);
rank
=(rank
+rank[temp])%2;         //更新n的偏移量,n的新偏移量等于n相对旧的根结点的偏移量+旧的根节点相对新的根节点的偏移量,
//因为旧的根节点已经附在新的根节点上,旧的根节点相对新的根节点的偏移量已更新
return father
;
}
void Union(int a,int b)         //a和b不属于同一个集合时,则将两个集合合并
{
int ra=Find_set(a);
int rb=Find_set(b);
father[ra]=rb;
//把ra接在rb上,需要更新ra的偏移量
//这是可以看成a与b在同一个集合中,第一条路径a相对ra的偏移量是rank[a],第二条路径a相对rb的偏移量是1+rank[b],
//容易算出把ra接到rb上,ra相对rb的偏移量就是a到rb的整段截去a到ra的一段,+3防止出现负数
rank[ra]=(rank[b]-rank[a]+1)%2;
}
int main()
{
int n,m,x,y,t,c=0;
scanf("%d",&t);
while(t--)
{
c++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
father[i]=i;
rank[i]=0;
}
int flag=0;
while(m--)
{
scanf("%d%d",&x,&y);
if(!flag)
{
int rx=Find_set(x);
int ry=Find_set(y);
if(rx==ry)          //若x和y属于统一集合
{
if(rank[x]==rank[y]) //x和y相对与根结点的偏移量相同,即与根结点关系相同
flag=1;
}
else
Union(x,y);
}
}
printf("Scenario #%d:\n",c);
if(flag)
printf("Suspicious bugs found!\n\n");
else
printf("No suspicious bugs found!\n\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: