永夜初晗凝碧天

本博客现已全部转移到新地址,欲获取更多精彩文章,请访问http://acshiryu.github.io/

导航

poj 2492 纪念下九月份AC的第一道题----并查集----有点重口味

最近开学了,没怎么做题,准备做一下搜索的,谁知道稀里糊涂看到了一道并查集,索性就试试(ps:这题也可以用搜索)

废话不多说,老规矩,原题再现:

A Bug's Life
Time Limit: 10000MS Memory Limit: 65536K
Total Submissions: 18911 Accepted: 6104

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!

题目有点怪,就是告诉你有n只虫子,m条信息,每一条信息的i和j有JQ,求出根据所给的信息能否判断出有搞基的虫子,并按照题目要求信息输出
这题用并查集解决起来很方便,当然搜索也可以解
首先分析第一组数据,则可知1和2异性,2和3也异性,可是1和3竟然也有JQ ,这是怎么回事?只能说他们在搞基,则输出Suspicious bugs found!
然后就是这题的处理办法,首先应该想到的是并查集,对于每一对有JQ的虫子,可以将他们分入到两个不同的并查集中,并记录跟这只虫子有JQ的虫子如果加入后存在冲突,则说明有搞基的虫子,没办法,这样就可以不用再考虑以后的虫子JQ了。
上面是大体思路,但有些小细节要考虑
如果那两只虫子之前都没有对象,都是处虫,则更新他们的对象信息;
如果只有其中的一个有对象,假设是a,而b没对象,则将b的对象更新为a,并且让a的对象和b同性,也就是入同一个并查集;
如果a和b都有对象,则有两种情况:
     a和b在同一个并查集里,则说明a和b有JQ,则可以不必考虑后面的虫子了;
     否则,将a和b之前的对象入同一个并查集,b和a之前的对象入同一个并查集;
这就是解这题我的思路,虽不是最优!
开始时因为很久没写并查集了,竟然写错了,WA了一个,然后就是对a和b都有对象的情况考虑不完整,也WA了一次,修正后果然AC了!

http://www.cnblogs.com/ACShiryu

参考代码:

 1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 int pre[2005]; //并查集常用
9 int com[2005]; //保存i的对象
10 int find(int x)
11 {//并查集的find
12 return pre[x]==x?x:pre[x]=find(pre[x]);
13 }
14 void join(int x , int y)
15 {//并查集的join
16 int px=find(x);
17 int py=find(y);
18 if(px!=py)
19 pre[px]=py;
20 }
21 int main()
22 {
23 int t ;
24 scanf("%d",&t);
25 int cas=1;
26 while (t--)
27 {
28 int n , m ;
29 scanf("%d%d",&n,&m);
30 int i ;
31 for (i=0;i<2005;i++)
32 {//pre初始化
33 pre[i]=i;
34 }
35 memset(com,-1,sizeof(com));
36
37 bool found = false; //判断是否找到搞基的虫子
38 for(i=0;i<m;i++)
39 {
40 int a,b;
41 scanf("%d%d",&a,&b);
42 if(found) //如果找到搞基的虫子,则不用考虑后面了
43 continue;
44 if (com[a]!=-1)
45 {//如果a有对象
46 if(com[b]!=-1)
47 {//b也有对象
48 if (find(a)==find(b))
49 {//并且a和b也在同一个并查集,则a和b在搞基
50 found=true;
51 }
52 //否则,将a和b之前的对象入同一个并查集,b和a之前的对象入同一个并查集
53 join(a,com[b]);
54 join(b,com[a]);
55 continue;
56 }
57
58 //b没对象,则将b的对象更新为a,并且让a的对象和b同性,也就是入同一个并查集
59 join(com[a],b);
60 com[b]=a;
61 }
62 else
63 {//a没对象
64 if(com[b]!=-1)
65 {//b有对象,则将a的对象更新为b,并且让b的对象和a同性,也就是入同一个并查集
66 join(a,com[b]);
67 com[a]=b;
68 }
69 else
70 {//a和b都没对象,则更新他们的对象信息
71 com[a]=b;
72 com[b]=a;
73 }
74 }
75 }
76 printf("Scenario #%d:\n",cas++);
77 if (found)
78 {
79 printf("Suspicious bugs found!\n");
80 }
81 else
82 {
83 printf("No suspicious bugs found!\n");
84 }
85 printf("\n");
86 }
87 return 0;
88 }

posted on 2011-09-15 22:24  ACShiryu  阅读(1573)  评论(0编辑  收藏  举报