prim算法(未优化版)

来源:互联网 发布:信鸽软件鑫 编辑:程序博客网 时间:2024/06/07 05:00
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
输出最小生成树的所有边的权值之和。
Sample Input
9 141 2 42 3 83 4 74 5 95 6 106 7 27 8 18 9 72 8 113 9 27 9 63 6 44 6 141 8 8
Sample Output
37


#include<stdio.h>
#include<string.h>
int a[1005][1005],dis[1005],vis[1005]={0}; //a用来存放:某点-某点的权值。
int indx,ans=0;                            //dis存放:当前到达的点到所有点的权值。
int n,m;                                   //vis标记走过的点。

void prim()
{
    int i,j,temp=9999999,ans=0;

    for(i=0;i<=n;i++)
        dis[i]=a[1][i];

    vis[1]=1;

    for(i=2;i<=n;i++)
    {
        temp=999999; //存储最小权值边。
        indx=0;
        for(j=0;j<=n;j++)
            if(dis[j]<temp && !vis[j])  //找出当前点到其他点 最小且没有走过的边的权值。
            {
                temp=dis[j];
                indx=j; //indx表示走到的点。
            }

        vis[indx]=1;
        ans+=temp;  //将最小边逐个相加。

        for(j=0;j<=n;j++)
            if(!vis[j] && a[indx][j]<dis[j])  //走到下一个点后更新权值。
                dis[j]=a[indx][j];            //注意:如果当前点比上一点到同一个点的权值大则不更新
                                              //例如 1-3权值为3 从1走到2后 2-3的权值为5 则不更新。
    }

        printf("%d\n",ans);
}
int main()
{
    int i,j,x,y,v;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                a[i][j]=999999;


        memset(vis,0,sizeof(vis));

        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&x,&y,&v);
            if(a[x][y]>v)
                a[x][y]=a[y][x]=v;
        }
        prim();
    }
    return 0;
}