poj 2524 Ubiquitous Religions

题目链接:http://poj.org/problem?id=2524

       实质上就是算经过所有的连边后,共有多少个不相交的集合。

       我采取的方法和解决1611 The suspects的方法是相同的。读者可以参考下。这里只讨论经过两次merge处理之后,怎样统计不相交集合的个数。先用sort将所有元素的祖先从小到大排序,这样是为了将具有相同祖先的元素紧挨在一起,而具有相同祖先的元素就是属于同一个集合的。最后再在所有学生中找出不具有相同祖先的元素个数,注意,p[i] = i 这些也属于具有不同祖先。

     

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 50000 + 5;
 6 int p[maxn];
 7 
 8 int find(int x)
 9 {
10     while (x != p[x])
11         x = p[x];
12     return x;
13 }
14 
15 void merge(int x, int y)
16 {
17     int fx = find(x);
18     int fy = find(y);
19     if (fx > fy)
20         p[fx] = fy;
21     else
22         p[fy] = fx;
23 }
24 
25 void merge1(int x, int y)
26 {
27     int fx = find(x);
28     int fy = find(y);
29     if (fx > fy)
30         p[x] = fy;
31     else
32         p[x] = fx;
33 }
34 
35 int main()
36 {
37     int i, n, m, a, b, num = 0;
38     while (scanf("%d%d", &n, &m) != EOF && (m || n))
39     {
40         if (m == 0)
41             printf("%d\n", n);    // 特殊情况,每个人都有自己不同于他人的宗教
42         else
43         {
44             for (i = 1; i <= n; i++)
45                 p[i] = i; // 假设每个人都有自己的宗教
46             for (i = 0; i < m; i++)
47             {
48                 scanf("%d%d", &a, &b);    
49                 merge(a, b);
50             }
51             for (i = 1; i <= n; i++)
52             {
53                 if (p[i] != i)
54                     merge1(i, p[i]);
55             }
56             sort(p+1, p+1+n);
57             int cnt = 1;       // 最少都会有一个信仰的宗教
58             for (i = 1; i < n; i++)
59             {    
60                 if (p[i] != p[i+1])
61                     cnt++;    
62             }
63             printf("Case %d: %d\n", ++num, cnt);
64         }
65     }
66     return 0;
67 }

 

posted @ 2013-09-03 23:25  windysai  阅读(209)  评论(0编辑  收藏  举报