这两道题都是比较简单的关于并查集使用的题目。有关并查集的知识,请参考:
(1) http://www.cnblogs.com/ACShiryu/archive/2011/11/24/unionset.html
(2)http://www.cnblogs.com/mikelin/archive/2010/08/11/1797556.html
其中:我们可以利用下面这段模板代码,做到熟记于心,即使变形也有思路
const int N=100; int pa[N]; int rank[N]; long int cnt; void make_set(int n) { for (int x=0;x<n;x++) { pa[x] = x; rank[x] = 0; } } int find_father(int x) { if(x != pa[x]) pa[x] = find_father(pa[x]); return pa[x]; } void union_set(int x, int y) { x = find_father(x); y = find_father(y); if (x==y) { return; } if(rank[x] > rank[y]) pa[y] = x; else { pa[x] = y; if(rank[x] == rank[y]) rank[y]++; } }
比如1161题:http://poj.org/problem?id=1611
只需要把上面的N改成需要的50000;
1161题代码:
1161 #include <iostream> #include <cstdio> using namespace std; const int N=50000; int pa[N]; int rank[N]; void make_set(int n) { for (int x=0;x<n;x++) { pa[x] = x; rank[x] = 0; } } int find_father(int x) { if(x != pa[x]) pa[x] = find_father(pa[x]); return pa[x]; } void union_set(int x, int y) { x = find_father(x); y = find_father(y); if(rank[x] > rank[y]) pa[y] = x; else { pa[x] = y; if(rank[x] == rank[y]) rank[y]++; } } int main() { int n,m,i,j,cnt; while (1) { cnt=0; scanf("%d %d",&n,&m); make_set(n); if (n==0 && m==0) break; for (i=0;i<m;i++) { int y=-1; int num; scanf("%d",&num); for (j=0;j<num;j++) { int x; scanf("%d",&x); if (y!=-1) union_set(x,y); y=x; } } int r=find_father(0); for (i=0;i<n;i++) { if(r==find_father(i)) cnt++; } printf("%d\n",cnt); } return 0; }
代码很简洁,类似的2524题:http://poj.org/problem?id=2524
#include <iostream> #include <cstdio> using namespace std; const int N=50001; int pa[N]; int rank[N]; long int cnt; void make_set(int n) { for (int x=1;x<n+1;x++) { pa[x] = x; rank[x] = 0; } } int find_father(int x) { if(x != pa[x]) pa[x] = find_father(pa[x]); return pa[x]; } void union_set(int x, int y) { x = find_father(x); y = find_father(y); if (x==y) { return; } if(rank[x] > rank[y]) pa[y] = x; else { pa[x] = y; if(rank[x] == rank[y]) rank[y]++; } } int main() { long int n,m,i; long int c=1; while (1) { scanf("%ld %ld",&n,&m); cnt=0; make_set(n); if (n==0 && m==0) break; for (i=0;i<m;i++) { long int x,y; scanf("%d %d",&x,&y); union_set(x,y); } for(i=1;i<=n; i++) if(pa[i] == i) cnt++; printf("Case %ld: %ld\n",c,cnt); c++; } return 0; }