最小生成树

 

#include <iostream>
#include <cstdio>
#define Max 1000
#define Inf 1000000
using namespace std;
int G[Max][Max];//图的邻接矩阵
bool use[Max];//标记C_1集合与C_2集合
int V,E;
int sum;//最小生成树的权值之和
int pre[Max];//记录路径
int mindist[Max];//记录最小距离

void prime()
{
    sum=0;
    for(int i=0; i<V; i++) //初始化
    {
        pre[i]=-1;
        use[i]=true;
        mindist[i]=Inf;
    }
    mindist[0]=0;
    for(int i=0; i<V; i++)
    {
        int Min=-1;
        for(int j=0; j<V; j++)//选取最短距离
            if(use[j]&&(Min==-1||mindist[Min]>mindist[j]))
                Min=j;
        if(Min==-1)
            break;
        sum+=mindist[Min];
        use[Min]=false;
        for(int j=0;j<V;j++)//更新最短距离
        {
            if(use[j]&&(mindist[j]>G[Min][j]))
            {
                mindist[j]=G[Min][j];
                pre[j]=Min;
            }

        }
    }
}


int main()
{
    scanf("%d%d",&V,&E);
    for(int i=0; i<V; i++)
        for(int j=0; j<V; j++)
            if(i==j)
                G[i][j]=0;
            else
                G[i][j]=Inf;
    int a,b,c;
    for(int i=0; i<E; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        G[a][b]=G[b][a]=c;
    }
    prime();
    printf("\n%d\n",sum);
    for(int i=0;i<V;i++)
        printf("%d——>%d\n",i,pre[i]);
    return 0;
}

 

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#define Max 1000
#define Inf 1000000
using namespace std;
struct edge
{
    int to;
    int value;
    friend bool operator<(edge a,edge b)
    {
        return a.value>b.value;
    }
};

vector<edge> G[Max];//邻接链表
int V,E;//顶点与边数
bool use[Max];//标记数组
int sum;//最小生成树的权值
int pre[Max];//记录每个点在前驱
int d[Max];//记录最短距离数组

void prime()
{
    for(int i=0;i<V;i++)
    {//初始化
        use[i]=true;
        pre[i]=-1;
        d[i]=Inf;
    }
    edge x,y;
    d[0]=0;//从0点开始
    x.to=0;
    x.value=0;
    priority_queue<edge> Que;//优先队列
    Que.push(x);
    while(!Que.empty())
    {
        x=Que.top();//取出最短距离
        Que.pop();
        if(use[x.to])
        {
            sum+=x.value;
            use[x.to]=false;
            for(int i=0;i<G[x.to].size();i++)//更新其他点的最短距离
            {
                y=G[x.to][i];
                if(use[y.to]&&d[y.to]>y.value)
                {
                    d[y.to]=y.value;
                    pre[y.to]=x.to;
                    Que.push(y);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d",&V,&E);
    int a,b,c;
    edge x,y;
    for(int i=0; i<E; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        x.to=a;
        y.to=b;
        x.value=y.value=c;
        G[a].push_back(y);
        G[b].push_back(x);
    }
    prime();
    printf("%d\n",sum);
    for(int i=0;i<V;i++)
        printf("%d——>%d\n",i,pre[i]);
    return 0;
}

并查集讲解链接

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#define Max 1000
#define Inf 10000000
using namespace std;
struct edge//边的结构体
{
    int point_1;
    int point_2;
    int value;
    friend bool operator< (const edge& a,const edge& b)//重载运算符<,因为sort使用该运算符
    {
        return a.value<b.value;
    }
};
edge G[Max];//边集表示图
int V,E;//顶点数和边数
int Set[Max];//图顶点的并查集
int high[Max];//并查集树高
int sum;//最小生成树的权值
int MST[Max];//最小生成树的边集
int M;

void init(int n)//并查集初始化
{
    for(int i=0; i<n; i++)
    {
        Set[i]=i;
        high[i]=1;
    }
}

int Find(int x)//查找x的根节点
{
    if(Set[x]==x)
        return x;
    else
        return Set[x]=Find(Set[x]);//路径压缩
}

void conbine(int x,int y)//合并x和y的集合
{
    int R_1=Find(x);
    int R_2=Find(y);
    if(R_1==R_2)
        return;
    if(high[R_1]>high[R_2])
        Set[R_2]=R_1;
    if(high[R_2]>high[R_1])
        Set[R_1]=R_2;
    if(high[R_1]==high[R_2])
    {
        Set[R_2]=R_1;
        high[R_1]++;
    }
}

bool same(int x,int y)//判断x与y是否在同一个集合
{
    return Find(x)==Find(y);
}

void krustra()
{
    init(V);
    sort(G,G+E);
    sum=0;
    int x,y;
    M=0;
    for(int i=0; i<E; i++)
    {
        x=G[i].point_1;
        y=G[i].point_2;
        if(!same(x,y))
        {
            //printf("%d\n",i);
            MST[M++]=i;
            conbine(x,y);
            sum+=G[i].value;
        }
    }
}

int main()
{
    scanf("%d%d",&V,&E);
    for(int i=0; i<E; i++)
        scanf("%d%d%d",&G[i].point_1,&G[i].point_2,&G[i].value);
    krustra();
    printf("%d\n",sum);
    for(int i=0; i<M; i++)
        printf("%d %d %d\n",G[MST[i]].point_1,G[MST[i]].point_2,G[MST[i]].value);
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值