这是一题典型的并查集的题。之前自己在做的时候是参考了网上的代码的,虽然是看懂了,不过感觉参考的并不是自己的。这次复习,就自己敲了一下,开始也没AC,因为在查找函数这里出了一点问题,后来再看书,然后自己模拟了一下,差不多知道错在哪儿了,改了一下,就AC了。虽然没有用到路径压缩什么的最优方法,不过总算是懂了并查集是怎么回事。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int u[1005];
void UFinit(int n)
{
int i;
for(i=1;i<=n;i++)
u[i]=i;
}
int UFfind(int e)
{
int j=e;
while(u[j]!=j){
j=u[j];
}
return j;
}
void UFunion(int i,int j)
{
int x=UFfind(i);
int y=UFfind(j);
if(x>y)
u[x]=y;
else
u[y]=x;
}
int main()
{
int n,m,x,y,cnt=0;
scanf("%d%d",&n,&m);
UFinit(n);
while(m--)
{
scanf("%d%d",&x,&y);
UFunion(x,y);
}
for(int i=1;i<=n;i++)
{
if(u[i]==i)
cnt++;
}
printf("%d\n",cnt-1);
return 0;
}
看了大神的优秀代码,优化了算法,先贴上代码,然后自己多敲几遍
#include<stdio.h>
#include<stdlib.h>
typedef struct ufset *UFset;
typedef struct ufset{
int *parent;
}UFS;
UFset UFinit(int size);
int UFfind(int e,UFset U);
void UFunion(int i,int j,UFset U);
int main()
{
int i,j = -1,n,m,x,y;
UFset U;
scanf("%d%d",&n,&m);
U = UFinit(n);
for (i = 0;i < m;i++){
scanf("%d%d",&x,&y);
UFunion(UFfind(x,U),UFfind(y,U),U);
}
for (i = 1;i <= n;i++)
if (U->parent[i] == i)j++;
printf("%d\n",j);
return 0;
}
UFset UFinit(int size)
{
int e;
UFset U = (UFset)malloc(sizeof *U);
U->parent = (int*)malloc((size+1)*sizeof(int));
for (e = 1;e <= size;e++)U->parent[e] = e;
return U;
}
int UFfind(int e,UFset U)
{
int i,j = e;
while (U->parent[j] != j)j = U->parent[j];
while (j != e){
i = U->parent[e];
U->parent[e] = j;
e = i;
}
return j;
}
void UFunion(int i,int j,UFset U)
{
if (U->parent[i] < U->parent[j])
U->parent[i] = j;
else
U->parent[j] = i;
}