这两道题都是比较简单的关于并查集使用的题目。有关并查集的知识,请参考:
(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;
}