1. 题目源地址:http://acm.hdu.edu.cn/showproblem.php?pid=1233
2. 简单思路:先对村庄距离从小到大排序,然后使用并查集的查找,一边查找一边加上村庄之间的距离,从而得到可以走通所有村庄的最短距离。
3. 源代码:
(1)并查集(此方法和Kruskal算法思想类似)
#include<iostream>
#include<algorithm>
using namespace std;
int father[110];
int N;
struct node
{
int from,to;
int dist;
}village[5050];
int cmp(const void *a,const void *b)
{
struct node *c=(node *)a;
struct node *d=(node *)b;
return c->dist - d->dist;
}
int find(int n)
{
if(father[n]==n)
return n;
else
return father[n]=find(father[n]);
}
int main()
{
int i,j;
int x,y;
while(cin>>N && N)
{
for(i=0;i<=N;i++)//注意这里是 <=N而不是 <N(Wrong Answer)(是因为我们在 find()函数里用到了 father[N]==N)
father[i]=i;
int sum=0;
for(i=0;i<(N*(N-1))/2;i++)
cin>>village[i].from>>village[i].to>>village[i].dist;
//注意:这题用了qsort()函数将village按dist从小到大排序,数组下标从0开始,故其他地方数组下标的也得从0开始
qsort(village,N*(N-1)/2,sizeof(village[0]),cmp);
for(i=0;i<(N*(N-1))/2;i++)
{
x=find(village[i].from);
y=find(village[i].to);
if(x!=y)
{
father[x]=y;
sum=sum+village[i].dist;
}
}
cout<<sum<<endl;
}
return 0;
}
(2)最小生成树Prim算法
//HOJ--1233:还是畅通工程 这题之前用并查集写过,但是利用Prim也可以解决
#include<iostream>
#include<memory.h>
#define MAX 110
#define INF 999999
using namespace std;
int N;
int map[MAX][MAX];
int visited[MAX],dist[MAX];
int Prim()
{
int i,j,pos,min;
memset(visited,0,sizeof(visited));
for(i=1;i<=N;i++)
dist[i]=map[1][i];
visited[1]=1;
for(i=1;i<N;i++)
{
min=INF;
for(j=1;j<=N;j++)
{
if(!visited[j] && dist[j]<min)
{
pos=j;
min=dist[j];
}
}
visited[pos]=1;
for(j=1;j<=N;j++)
{
if(!visited[j] && map[pos][j]<dist[j])
dist[j]=map[pos][j];
}
}
int sum=0;
for(i=1;i<=N;i++)
{
sum=sum+dist[i];
}
return sum;
}
int main()
{
int a,b,d;
int i,j;
while(cin>>N && N)
{
//初始化map[][]
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
if(i==j)
map[i][j]=map[j][i]=0;
for(i=1;i<=(N*(N-1))/2;i++)
{
cin>>a>>b>>d;
map[a][b]=map[b][a]=d;
}
cout<<Prim()<<endl;
}
return 0;
}