最小生成树

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
原文地址:https://www.cnblogs.com/wangkaipeng/p/6445030.html