首页 > 代码库 > 51nod1212 无向图最小生成树(Prim)

51nod1212 无向图最小生成树(Prim)

题目描述:

N个点M条边的有向连通图,每条边有一个权值,求该图的最小生成树。

Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
OutPut
输出最小生成树的所有边的权值之和。
Input示例
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Output示例
37题目分析:Prim算法,每次选择最短的线段,并将产生最短线段的点,拉入最小生成树序列,直到n个点全部进入序列。AC代码:
/**
 *1、最小生成树Prim算法(2015.1.1)
 *2、Kruskal算法
 */
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int G[1001][1001];//邻接矩阵
int vis[1001],lowc[1001];
int prim(int G[][1001],int n){
    int i,j,p,minc,res=0;
    memset(vis,0,sizeof(vis));
    vis[1]=1;//从1开始访问
    for(i=2;i<=n;i++) lowc[i]=G[1][i];
    for(i=2;i<=n;i++){
        minc=inf; p=-1;
        for(j=1;j<=n;j++){
            if(vis[j]==0&&lowc[j]<minc){
                minc=lowc[j]; p=j;
            }
        }
        //cout<<minc<<endl;
        if(inf==minc) return -1;//原图不联通
        res+=minc; vis[p]=1;
        for(j=1;j<=n;j++){//更新lowc[]
            if(vis[j]==0&&lowc[j]>G[p][j]){
                lowc[j]=G[p][j];
            }
        }
    }
    return res;
}

int main()
{
    int n,m;
    while(cin>>n>>m){
        int x,y,w;
        memset(G,inf,sizeof(G));//首先记录所有边的权为inf
        for(int i=1;i<=m;i++){
            cin>>x>>y>>w;
            G[x][y]=G[y][x]=w;
            //cout<<G[x][y]<<endl;
        }
        //int res=prim(n);
        cout<<prim(G,n)<<endl;
    }
	return 0;
}


51nod1212 无向图最小生成树(Prim)