无向图最小生成树

基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
Output
输出最小生成树的所有边的权值之和。
Input示例
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Output示例
37

Prime算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int cost[1020][1020];//cost[u][v]表示边e=(u,v)的权值(不存在的情况下设为INF)
int mincost[1020];//从集合X出发的边到每个顶点的最小权值
bool used[1020];//顶点i是否包含在集合X中
int N,M,S,E,W;
int prime()
{
    for(int i=1;i<=N;i++)
    {
        mincost[i]=INF;
        used[i]=false;
    }
    mincost[1]=0;
    int res=0;
    while(true)
    {
        int v=-1;//从不属于X的顶点中选取从X到其权值最小的顶点
        for(int u=1;u<=N;u++)
        {
            if(!used[u]&&(v==-1||mincost[u]<mincost[v]))
                v=u;
        }
        if(v==-1)break;
        used[v]=true;//把顶点v加入X
        res+=mincost[v];//把边的长度加到结果里
        for(int u=1;u<=N;u++)
        mincost[u]=min(mincost[u],cost[v][u]);
    }
    return res;
}
int main()
{
    cin>>N>>M;
    memset(cost,INF,sizeof(cost));
    for(int i=0;i<M;i++)
    {
        cin>>S>>E>>W;
        cost[S][E]=min(W,cost[S][E]);
        cost[E][S]=min(W,cost[E][S]);
    }
    cout<<prime()<<endl;
    return 0;
}

Kruskal算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
struct edge{int u,v,cost;};
bool cmp(const edge& e1,const edge& e2){
    return e1.cost<e2.cost;
}
edge es[50020];
int V,E;//顶点数和边数
int par[1020];//父亲
int rank[1020];//树的高度
//初始化V个元素
void init()
{
    for(int i=0;i<V;i++)
    {
        par[i]=i;
        rank[i]=0;
    }
}
//查询树的根
int find(int x)
{
    if(par[x]==x)
        return x;
    return par[x]=find(par[x]);
}
//合并x和y所属的集合
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]++;
    }
}
//判断x和y是否属于同一个集合
bool same(int x,int y)
{
    return find(x)==find(y);
}
int kruskal()
{
    sort(es,es+E,cmp);//按照edge,cost的顺序从大到小
    init();//并查集的初始化
    int res=0;
    for(int i=0;i<E;i++)
    {
        edge e=es[i];
        if(!same(e.u,e.v))
        {
            unite(e.u,e.v);
            res+=e.cost;
        }
    }
    return res;
}
int main()
{
    cin>>V>>E;
    for(int i=0;i<E;i++)
    cin>>es[i].u>>es[i].v>>es[i].cost;
    cout<<kruskal()<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ultrasurreal/article/details/80352772