您的位置:首页 > 其它

HDU 1863 畅通工程(最小生成树prim算法)

2011-05-31 17:25 399 查看
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define  M 101
int map[M][M],v,arc;
void init(){
//用-1标记距离为无穷大。
memset(map,-1,sizeof(map));
int from,to,weight;
while(arc--){
cin>>from>>to>>weight;
if(map[from][to]<0 || map[from][to]>weight)
map[from][to]=map[to][from]=weight;//无向图,对称性。
}
}
int MTS_prim(){
bool visited[M];
int dist[M],i=1,j,k,MTSdist=0;
memset(dist,-1,(v+1)*sizeof(int));
memset(visited,false,(v+1)*sizeof(bool));
visited[i]=true;
dist[i]=0;

for(j=1;j<v;j++){
for(k=1;k<=v;k++){
if(!visited[k] && map[i][k]!=-1
&& (dist[k]<0 || map[i][k]<dist[k]) )
dist[k]=map[i][k]; //根据目前的点,更新(已经在树上的点到没有到的点)距离最短的点,
}
int minp=0;
for(i=1;i<=v;i++) //找到更新之后权值最小的点,标记入minp中;
if( !visited[i] && dist[i]>-1  && ( !minp  || dist[minp]>dist[i] ) )
minp=i;
if(!minp) //没有找到,返回错误
return -1;
visited[minp]=true;
MTSdist+=dist[minp];
i=minp;
}

for(i=1;i<=v;i++)// 判断是否所有的点都已经在生成树中
if(!visited[i])
return -1;

return MTSdist;
}
int main(){
while(cin>>arc>>v && arc){
init();
int MTSdist=MTS_prim();
MTSdist<0?cout<<"?"<<endl:cout<<MTSdist<<endl;
}

return 0;
}


求MST的一般算法可描述为:针对图G,从空树T开始,往集合T中逐条选择并加入n-1条安全边(u,v),最终生成一棵含n-1条边的MST。

  当一条边(u,v)加入T时,必须保证T∪{(u,v)}仍是MST的子集,我们将这样的边称为T的安全边。

  用伪代码可将算法描述为:

  GenerieMST(G){//求G的某棵MST

  T〈-¢; //T初始为空,是指顶点集和边集均空

  while T未形成G的生成树 do{

  找出T的一条安全边(u,v);//即T∪{(u,v)}仍为MST的子集

  T=T∪{(u,v)}; //加入安全边,扩充T

  }

  return T; //T为生成树且是G的一棵MST

  }

  注意:

  下面给出的两种求MST的算法均是对上述的一般算法的求精,两算法的区别仅在于求安全边的方法不同。

  为简单起见,下面用序号0,1,…,n-1来表示顶点集,即是:

  V(G)={0,1,…,n-1},

  G中边上的权解释为长度,并设T=(U,TE)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: