zoukankan      html  css  js  c++  java
  • 最小生成树 算法

    nyoj 38 http://acm.nyist.net/JudgeOnline/problem.php?pid=38


    prim  克鲁斯卡尔  两个算法

    首先说说 克鲁斯卡尔算法,按照边的从小到大排序之后,利用并查集的思想,不断并。直到并出n-1条边。

     
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    
    using namespace std;
    typedef long long int LL;
    const int INF=2e9+1e8;
    const double eps=1e-8;
    const int MM=500+5;
    
    
    struct Edge
    {
        int s,t,val;
    };
    
    Edge edge[MM*MM/2];
    int m,n;
    int pre[MM];
    void init_pre()
    {
        for(int i=0; i<=n; i++)
            pre[i]=i;
    }
    
    bool cmp(Edge a,Edge b)
    {
        return a.val<b.val;
    }
    int getfa(int x)
    {
        return pre[x]==x?x:pre[x]=getfa(pre[x]);
    }
    bool merges(int x,int y)
    {
        int fx=getfa(x),fy=getfa(y);
        if(fx==fy) return false;
        else
        {
            pre[fx]=fy;
            return true;
        }
    }
    int Kruskal()
    {
        sort(edge+1,edge+1+m,cmp);
        int tot=0;
        for(int i=1; i<=m; i++)
        {
            if(merges(edge[i].s,edge[i].t))
            {
                tot+=edge[i].val;
            }
        }
        return tot;
    }
    int main()
    {
        int ncase;
        scanf("%d",&ncase);
        while(ncase--)
        {
            scanf("%d%d",&n,&m);
            init_pre();
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].val);
            }
            int minn=INF;
            for(int i=1; i<=n; i++)
            {
                int temp;
                scanf("%d",&temp);
                minn=min(temp,minn);
            }
            printf("%d
    ",Kruskal()+minn);
        }
        return 0;
    }
            



    prim

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
    3).重复下列操作,直到Vnew = V:
    a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
    b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树

    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    using namespace std;
    const int maxn=505;
    const int INF=0x3f3f3f3f;
    int map[maxn][maxn];
    int dis[maxn];
    int vis[maxn];
    int N;//N组测试数据
    int V;//点的数量
    int E;//边的数量
    int min_num;//最小外接花费
    void init()
    {
        scanf("%d%d",&V,&E);
        for(int i=0; i<=V; i++)//初始化图
            for(int j=0; j<=V; j++)
                i==j?map[i][j]=0:map[i][j]=INF;
        while(E--)//建图
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;//无向图
            map[b][a]=c;
        }
        min_num=INF;
        for(int i=1; i<=V; i++)
        {
            int x;
            scanf("%d",&x);
            min_num=min(min_num,x);//生成树连接到外界的最小花费
            dis[i]=map[i][1];//从1开始构造最小生成树
        }
        memset(vis,0,sizeof(vis));
        vis[1]=1;//0代表是外界
    }
    void Prim()
    {
        int min_cost=0;//初始化最小花费
        for(int i=1; i<V; i++)
        {
            int minn=INF;
            int point_minn;
            for(int j=1; j<=V; j++)
                if(vis[j]==0&&minn>dis[j])
                {
                    point_minn=j;
                    minn=dis[j];
                }
            if(minn==INF)
                break;
            min_cost+=dis[point_minn];
            vis[point_minn]=1;
            for(int j=1; j<=V; j++)
                if(vis[j]==0&&dis[j]>map[point_minn][j])
                    dis[j]=map[point_minn][j];
        }
        printf("%d
    ",min_cost+min_num);
    }
    int main()
    {
        scanf("%d",&N);
        while(N--)
        {
            init();
            Prim();
        }
        return 0;
    }


  • 相关阅读:
    centos7 docker安装awvs
    screen命令简介-实现linux多窗口
    linux命令重命名
    iptables防止nmap扫描
    cobal strike could not start listener address already in use (bind failed)
    docker简介及安装
    「Sqlserver」数据分析师有理由爱Sqlserver之二-像使用Excel一般地使用Sqlserver
    「Sqlserver」数据分析师有理由爱Sqlserver之一-好用的插件工具推荐
    「PowerBI」分析服务多维数据结构重回关系数据库的一大绝招
    「数据分析」Sqlserver中的窗口函数的精彩应用之数据差距与数据岛(含答案)
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7207966.html
Copyright © 2011-2022 走看看