zoukankan      html  css  js  c++  java
  • 最小生成树(HDOJ 1863)

    畅通工程

    http://acm.hdu.edu.cn/showproblem.php?pid=1863

    1.Prim算法:

    Prim算法是由一个点(最初的集合)向外延伸,找到与集合相连权值最小的边,

    然后把对应顶点拉到集合里,直到所有的顶点全部在集合里为止。

    Prim算法的演示如下:

    http://sjjp.tjuci.edu.cn/sjjg/DataStructure/DS/web/flashhtml/prim.htm

    #include <stdio.h>
    const int INF=9999999;
    const int MAXV=101;
    int map[MAXV][MAXV];
    int res;
    void Prim(int map[MAXV][MAXV],int numV)
    {
        int i,j,k;
        int lowcost[MAXV];
        lowcost[1]=0;         //顶点1已经在集合里
        for(i=2;i<=numV;i++)
        {
            lowcost[i]=map[1][i];    //lowcost[]里存储的是当前集合相连的所有边的权值
        }
        for(i=2;i<=numV;i++)       //依次循环除1以外的其余点,把它拉集合里
        {
            int min=INF;
            k=1;            //k初始化为1,是为了避免下一个循环里的k=j没执行,k为任意值,lowcost[k]数组溢出
            for(j=2;j<=numV;j++)
            {
                if(lowcost[j]!=0&&lowcost[j]<min)   //查找集合外与集合相连的点
                {
                    min=lowcost[j];
                    k=j;
                }
            }
            res+=min;
            lowcost[k]=0;       //lowcost[k]=0表示顶点k被拉到集合里
            for(j=2;j<=numV;j++)
            {
                if(lowcost[j]!=0&&map[k][j]<lowcost[j])
                {
                    lowcost[j]=map[k][j];   
                }   //顶点k加入集合后,集合发生变化,更新与集合相连边的权值
            }
        }
    }
    int main()
    {
        int n,m,i,j;
        int begin,end,w;
        while(scanf("%d%d",&n,&m)!=EOF&&n)
        {
            for(i=1;i<=m;i++)
            {
                for(j=1;j<=m;j++)
                {
                    if(i==j)
                        map[i][j]=0;
                    if(i!=j)
                        map[i][j]=INF;
                }     //创建邻接矩阵
            }
            for(i=1;i<=n;i++)
            {
                scanf("%d%d%d",&begin,&end,&w);
                map[begin][end]=w;
                map[end][begin]=w;
            }
            res=0;
            Prim(map,m);
            if(res>INF)    //表示lowcost里还有INF,即图不连通
                printf("?\n");
            else
                printf("%d\n",res);
        }
        return 0;
    }
    View Code

    2.Kruskal算法

    Kruskal算法是先将所有的边按权值从小到大排序,在依次加边,

    直到加了(顶点数-1)条边。注意:加边时避免出现环。

    #include <stdio.h>
    #include <stdlib.h>
    struct node
    {
        int begin;
        int end;
        int w;
    };
    node edge[5000];
    int res,count;
    int cmp(const void *p1,const void *p2)
    {
        return (*(node*)p1).w-(*(node*)p2).w;
    }
    int Find(int *parent,int f)
    {
        while(parent[f]!=f)
            f=parent[f];
        return f;
    }   //寻找根节点,有点类似于并查集
    void Kruskal(int numV,int numE)
    {
        int n,m,i;
        int parent[101];
        for(i=1;i<=numV;i++)
            parent[i]=i;
        for(i=0;i<numE;i++)
        {
            n=Find(parent,edge[i].begin);
            m=Find(parent,edge[i].end);
            if(n!=m)
            {
                parent[n]=m;
                count++;
                res+=edge[i].w;
            }//如果一条边的两个端点的的节点相同,加上这条边后就出现环
        }
    }
    int main()
    {   
        int n,m,i;
        while(scanf("%d%d",&n,&m)!=EOF&&n)
        {
            for(i=0;i<n;i++)
            {
                scanf("%d%d%d",&edge[i].begin,&edge[i].end,&edge[i].w);
            }
            qsort(edge,n,sizeof(edge[0]),cmp);
            res=count=0;
            Kruskal(m,n);
            if(count<m-1)    //加入的边数<顶点数-1,说明图不连通
                printf("?\n");
            else
                printf("%d\n",res);
        }
        return 0;
    }
    View Code

    小结:Prim算法是基于顶点来加边,而Kruskal算法是基于边

  • 相关阅读:
    字符串匹配之BF算法
    python里的反射(自学习)
    python的super()以及父类继承
    @staticmethod
    @classmethod
    scrapy
    mongodb
    js注入提取伪元素选择器
    execjs
    base64解密
  • 原文地址:https://www.cnblogs.com/chiry/p/3234446.html
Copyright © 2011-2022 走看看