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 }