• 最小生成树


    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
  • 相关阅读:
    收集一些关于前端的网站(持续更新)
    关于表单设计(登录)的几点感悟
    css样式表中的样式覆盖顺序(转)
    UI设计常用网站(随时更新)
    关于ps安装遇到的问题解决(转载整理)
    【工作记录】解决溢出div自适应的高度问题
    Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https, chrome-extension-resource. 报错处理
    [css]img垂直居中的方法
    iOS学习第三天杂记
    iOS学习第二天杂记--UI
  • 原文地址:https://www.cnblogs.com/wangkaipeng/p/6445030.html
Copyright © 2020-2023  润新知