http://acm.hdu.edu.cn/showproblem.php?pid=1232
这并不是道难题,开始不会用并查集,把题目想得难了!这道题目是要我们求出要建的道路的最少条数,就是
先把之前有连通的点归到一个集合中,然后每次输入两点的时候就将两个点所属的集合并成一个集合,然后用
许多个不相交的集合来表示这些点的连通情况。而并查集的优点就是用树来表示集合。每棵树表示一个集合,
因此树的形态无关紧要,把遍历过的结点都改成树根的儿子就行了。
贴下我的代码:
#include <stdio.h>
int A[1050];
/* 找x所在的树根,一层一层找 */
int find(int x)
{
return A[x] == x? x : (A[x] = find(A[x]));
}
/*将点的集合合并,如果两点所在的集合为不同的集合*/
void h(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 != f2)
A[f1] = f2;
}
int main()
{
int n,m,i,x,y,cnt;
while(scanf("%d",&n),n)
{
for(i = 1; i <= n; i++)
A[i] = i; //初始化并查集
scanf("%d",&m);
for(i = 0; i < m; i++)
{
scanf("%d%d",&x,&y);
h(x,y);
}
cnt = -1; //初始化为-1的好处是后面不容易出错
for(i = 1;i <= n; i++) //找树根为点本身的点的个数,也可以说是集合个数
if(A[i] == i)
cnt++;
printf("%d\n",cnt);
}
return 0;
}
其实还是邪恶的参考了白书的写法,得看的东西真多!!! 何时才会最短路呢?
10月4号不看书用c++写了一遍,看来熟练了不少,用了几分钟就敲完了,以下是c++代码:
#include<iostream>
using namespace std;
#define MAX 1005
int p[MAX];
int find(int x)
{
return p[x] == x ? x : ( p[x] = find(p[x]) );
}
void merge( int a, int b)
{
int x = find(a);
int y = find(b);
if( x != y) p[x] = y;
}
int main()
{
int N,M,i,cnt,a,b;
while(cin >> N, N)
{
cin >> M;
for( i = 1;i <= N; i++)
p[i] = i;
for( i = 0;i < M; i++)
{
cin >> a >> b;
merge(a,b);
}
cnt = -1;
for( i = 1; i <= N; i++)
if(p[i] == i) cnt++;
cout << cnt << endl;
}
return 0;
}
浙公网安备 33010602011771号