超级传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=1233
题目大意:
给出N个点之间的距离,要求建公路让N个点互相可达,求公路最短的长度。
题目分析:
由题目意思可得这一题是最小生成树的问题
下面用Prim的实现了一下,Prim的大致方法:
Ø
初始时,U={u0},TE=f;
Ø
在所有u属于U、v属于V-U的边(u,v)中选择一条权值最小的边,不妨设为(u,v);
Ø
(u,v) 加入TE,同时将v 加入U;
Ø
重复(2)、(3),直到U=V为止;
#include<iostream>
using namespace std;
#define INFINITE 900000000
const int max_node = 500;
int G[max_node][max_node]; //邻接矩阵存储地图
int dis[max_node]; //路径长度
int f[max_node]; //记录该点是否加入了U
int N;
int Prim_mst()
{
int i,j,k;
int min,temp;
int ans = 0;
//把1点加入U中
dis[1] = 0;
f[1] = 1;
//先把所有距离初始化
for(i=2;i<=N;i++)
{
if(G[i][1] != -1)
{
dis[i] = G[i][1];
}
else
{
dis[i] = INFINITE;
}
}
for(k=0;k<N-1;k++) //一共要循环n-1次
{
//从V-U中找出一个到T=(U,TE)距离最短的点
min = INFINITE;
for(i=2;i<=N;i++) //这一题是从1开始存储的,这点也要非常小心,看清楚每一题是从0开始还是从1开始存
{
if(f[i] != 1) //i不是U中的点
{
if(dis[i] < min)
{
min = dis[i];
temp = i;
}
}
}
//把这一点加入U中
f[temp] = 1;
ans += dis[temp];
//根据这一点,更新其他点的距离
for(i=1;i<=N;i++)
{
if(f[i] != 1) //i不是U中的点
{
if(G[i][temp] != -1 && (G[i][temp]) < dis[i])
{
dis[i] = G[i][temp];
}
}
}
}
return ans;
}
int main()
{
int temp;
int i,j;
int a,b,l;
int sum;
while(scanf("%d",&N) != EOF)
{
memset(G,255,sizeof(G)); //把所有点设为-1,-1表示不可达
memset(dis,0,sizeof(dis));
memset(f,0,sizeof(f));
if(N == 0) break;
temp = N*(N-1)/2;
for(i=0;i<temp;i++)
{
scanf("%d %d %d",&a,&b,&l);
G[a][b] = l; //这里一定要注意双向
G[b][a] = l; //很多图论的问题都有单向和双向的区分,一不小心就WA了。。。
}
printf("%d\n",Prim_mst());
}
return 0;
}