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

    1.prim

    假设有一颗只包含一个顶点v的树T。然后贪心地选取T和其他顶点之间相连的最小权值的边,并把它加到T中。不断进行这个操作,就可以得到最小生成树。

    #include<iostream>
    using namespace std;
    #define INF 10000000
    const int maxv=1005;
    int V,E,start;
    int cost[maxv][maxv];
    int mincost[maxv];
    int used[maxv];
    int prim()
    {
        for(int i=0;i<V;i++)
        {
            mincost[i]=INF;
            used[i]=0;
        }
        mincost[0]=0;
        int res=0;
    
        while(true)
        {
            int v=-1;
            //从不属于x的顶点中选取从x到其权值最小的顶点
            for(int u=0;u<V;u++)
            {
                if(!used[u]&&(v==-1||mincost[v]>mincost[u])) v=u;
            }
    
            if(v==-1) break;
            used[v]=1;
            res+=mincost[v];
            for(int u=0;u<V;u++)
            {
                mincost[u]=min(mincost[u],cost[v][u]);
            }
        }
        return res;
    }
    
    int main()
    {
        cin>>V>>E;
        int from,to,value;
        for(int i=0;i<V;i++)
        {
            for(int j=0;j<V;j++)
            {
                cost[i][j]=INF;
            }
        }
        for(int i=0;i<E;i++)
        {
            cin>>from>>to>>value;
            cost[from][to]=value;
        }
        cout<<prim()<<endl;
    }
    View Code

    2.kruskal

    按照边的权值的顺序从小到大查看一遍,如果不产生圈,就把当前这条边加入到生成树中。先理解并查集就很好理解了。

    //克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=1005;
    const int maxe=10005;
    struct edge
    {
        int from,to,cost;
        edge(){}
        edge(int ff,int tt,int cc)
        {
            from=ff;
            to=tt;
            cost=cc;
        }
    };
    bool cmp(edge e1,edge e2)
    {
        return e1.cost<e2.cost;
    }
    int V,E;
    edge es[maxe];
    //并查集
    int rank[maxn];
    int par[maxn];
    void init(int x)
    {
        for(int i=0;i<x;i++)
        {
            par[i]=i;
            rank[i]=0;
        }
    }
    int find(int x)
    {
        if(par[x]==x) return x;
        else return par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        x=find(x);
        y=find(y);
        if(x==y) return;
        if(rank[x]<rank[y]) par[x]=y;
        else
        {
            par[y]=x;
            if(rank[x]==rank[y]) rank[x]++;
        }
    }
    bool same(int x,int y)
    {
        return find(x)==find(y);
    }
    
    int kruskal() //n为边的数量
    {
        sort(es,es+E,cmp);
        init(V); //并查集的初始化
        int res=0;
        for(int i=0;i<E;i++)
        {
            edge e=es[i];
            if(!same(e.from,e.to))
            {
                unite(e.from,e.to);
                res+=e.cost;
            }
        }
        return res;
    }
    
    int main()
    {
        cin>>V>>E;
        int from,to,value;
        for(int i=0;i<E;i++)
        {
            cin>>from>>to>>value;
            es[i]=edge(from,to,value);
        }
        cout<<kruskal()<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/wangkaipeng/p/6445030.html
Copyright © 2011-2022 走看看