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

#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)。

你可能感兴趣的:(HDU 1863 畅通工程(最小生成树prim算法))