这是一个全裸的并查集,其实就是求有多少个不同的连通分量。第一次用并查集,理解的差不多了,接下来就是应用啦。
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int maxn = 1002;
int p[maxn]; //p用来记录父节点
int rank[maxn]; //rank用来记录节点数
int find(int x)
{
return p[x] == x? x : p[x] = find(p[x]);
}
void Union(int x, int y)
{
int i = find(x);
int j = find(y);
if(i == j) return ;
if(rank[i] > rank[j]) //压缩路径
{
p[j] = i; //如果i节点数大于j的节点数那么,则令j指向i;
}
else
{
p[i] = j; //如果j节点数大于i的节点数那么,则令i指向j;
if(rank[i] == rank[j]) //压缩路径
{
rank[j]++;
}
}
}
int main()
{
int N, M;
while(~scanf("%d", &N) && N)
{
int i, j, tot;
memset(rank, 0, sizeof(rank));
for(i = 0 ; i <= N; i++) p[i] = i;
for(scanf("%d", &M); M > 0; M--)
{
int a, b;
scanf("%d%d", &a, &b);
Union(a, b);
}
for(tot = -1, i = 1 ; i <= N; i++) if(p[i] == i) tot++;
printf("%d\n", tot); //tot
}
return 0;
}
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int maxn = 1002;
int p[maxn]; //p用来记录父节点
int rank[maxn]; //rank用来记录节点数
int find(int x)
{
return p[x] == x? x : p[x] = find(p[x]);
}
void Union(int x, int y)
{
int i = find(x);
int j = find(y);
if(i == j) return ;
if(rank[i] > rank[j]) //压缩路径
{
p[j] = i; //如果i节点数大于j的节点数那么,则令j指向i;
}
else
{
p[i] = j; //如果j节点数大于i的节点数那么,则令i指向j;
if(rank[i] == rank[j]) //压缩路径
{
rank[j]++;
}
}
}
int main()
{
int N, M;
while(~scanf("%d", &N) && N)
{
int i, j, tot;
memset(rank, 0, sizeof(rank));
for(i = 0 ; i <= N; i++) p[i] = i;
for(scanf("%d", &M); M > 0; M--)
{
int a, b;
scanf("%d%d", &a, &b);
Union(a, b);
}
for(tot = -1, i = 1 ; i <= N; i++) if(p[i] == i) tot++;
printf("%d\n", tot); //tot
}
return 0;
}