POJ 1611 The Suspects

The Suspects
Time Limit: 1000MS   Memory Limit: 20000K
Total Submissions: 17669   Accepted: 8547

Description

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others.  In the Not-Spreading-Your-Sickness University (NSYSU), there are many student groups. Students in the same group intercommunicate with each other frequently, and a student may join several groups. To prevent the possible transmissions of SARS, the NSYSU collects the member lists of all student groups, and makes the following rule in their standard operation procedure (SOP).  Once a member in a group is a suspect, all members in the group are suspects.  However, they find that it is not easy to identify all the suspects when a student is recognized as a suspect. Your job is to write a program which finds all the suspects.

Input

The input file contains several cases. Each test case begins with two integers n and m in a line, where n is the number of students, and m is the number of groups. You may assume that 0 < n <= 30000 and 0 <= m <= 500. Every student is numbered by a unique integer between 0 and n−1, and initially student 0 is recognized as a suspect in all the cases. This line is followed by m member lists of the groups, one line per group. Each line begins with an integer k by itself representing the number of members in the group. Following the number of members, there are k integers representing the students in this group. All the integers in a line are separated by at least one space.  A case with n = 0 and m = 0 indicates the end of the input, and need not be processed.

Output

For each case, output the number of suspects in one line.

Sample Input

100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0

Sample Output

4
1
1

继POJ 1182(好像是这个) 食物链之后第二次写并查集问题这一次是自己写出来的,哈哈哈,虽然RE一次,还是蛮得意的
出现Runtime Error的可以跑一下下面这组测试数据(我根据Discuss里的提示自己想的哦):
100 4
2 0 1
5 10 7 13 12 14
3 13 10 17
2 7 8
如果你的程序没有跑死,那么正确答案是:2
问题就在于第二个集合和第三个集合中一部分已经属于同一个集合,如果不加判断就进行合并的话,可能会导致并查集的树变成了一个环,根节点消失了,再Find()的时候就会无穷递归下去,导致堆栈溢出

源代码如下:

 1 #include<stdio.h>
 2 
 3 long father[30050];
 4 
 5 void MakeSet (long n)
 6 {
 7     int i;
 8     for (i = 0; i < n; i++)
 9         father[i] = i;
10 }
11 
12 long Find (long t)
13 {
14     if (t != father[t])
15         return father[t] = Find (father[t]);
16     return father[t];
17 }
18 
19 int main()
20 {
21     long i, n, m, k, pre, next, ans;
22     while (scanf ("%ld %ld", &n, &m) == 2)
23     {
24         if (n == 0 && m == 0)
25             break;
26         MakeSet (n);
27         ans = 0;
28         while (m--)
29         {
30             scanf ("%ld", &k);
31             scanf ("%ld", &pre);
32             for (i = 2; i <= k; i++)
33             {
34                 if (Find (pre) == 0)
35                     break;
36                 scanf ("%ld", &next);
37                 if (Find (pre) != Find (next))
38                     father[Find (pre)] = next;
39                 pre = next;
40             }
41             for (; i <= k; i++)
42             {
43                 scanf ("%ld", &next);
44                 father[Find (next)] = 0;
45             }
46         }
47         for (i = 0; i < n; i++)
48             if (Find (i) == 0)
49                 ans++;
50         printf ("%ld\n", ans);
51     }
52     return 0;
53 }
[C]

 

posted @ 2013-05-23 16:52  ~~Snail~~  阅读(143)  评论(0编辑  收藏  举报