最小生成树基础

来源:互联网 发布:微信截图软件 编辑:程序博客网 时间:2024/05/13 13:07

微笑课本内容小改动~

prim算法:

#include<cstdio>#include<cstdlib>#include<cmath>#include<map>#include<queue>#include<stack>#include<vector>#include<algorithm>#include<iomanip>#include<cstring>#include<string>#include<iostream>const int MAXN=100+10;const int INF=999999;using namespace std;int G[MAXN][MAXN];int cp[MAXN];int dis[MAXN];int sum;void prim(int n, int v){    int i,j;    for(i=0; i<n; i++){        dis[i]=G[v][i];        cp[i]=v;    }    for(i=1; i<n; i++){        int min=INF;        int k=v;        for(j=0; j<n; j++){            if(dis[j] && dis[j]<min){                min=dis[j];                k=j;            }        }printf("%d <-> %d = %d\n", cp[k], k, min);//打印两顶点与两点间权值        sum+=dis[k];//计算最短路径和        dis[k]=0;//加入集合        for(j=0; j<n; j++){            if(G[j][k] && G[j][k]<dis[j]){//更新候选边                dis[j]=G[j][k];                cp[j]=k;            }        }    }    printf("%d\n", sum);}int main(){    //freopen("in.txt","r",stdin);    int n,m;    while(scanf("%d%d", &n,&m), n+m)//节点为0~n-1    {        sum=0;        int i,j;        for(i=0; i<n; i++){//初始化图            for(j=0; j<n; j++){                if(i==j){ G[i][j]=0; continue;}                G[i][j]=INF;            }        }        for(i=1; i<=m; i++){            int u,v,w;            scanf("%d%d%d", &u,&v,&w);            G[u][v]=w;            G[v][u]=w;        }        prim(n, 0);    }    return 0;}

kruskal算法:

#include<cstdio>#include<cstdlib>#include<cmath>#include<map>#include<queue>#include<stack>#include<vector>#include<algorithm>#include<cstring>#include<string>#include<iostream>const int MAXN=5000+10;const int INF=99999;using namespace std;int fa[101];int sum;typedef struct edge{    int u,v,w;}*Edge;bool cmd(edge e1, edge e2){    return e1.w<e2.w;}int find(int x){    if(fa[x]==x) return x;    return fa[x]=find(fa[x]);}void kruskal(int n, Edge E){    int k=1,j=0;    int u1,v1,c1,c2;    for(int i=1; i<=n; i++) fa[i]=i;    while(k<n)//n个点只需要找n-1条边    {        u1=E[j].u;        v1=E[j].v;        c1=find(u1);        c2=find(v1);        if(c1!=c2){//u1与v1属于不同的集合            fa[c1]=c2;//合并            k++;            sum+=E[j].w;cout<<u1<<" <-> "<<v1<<" = "<<E[j].w<<endl;//打印方案        }        j++;    }    printf("%d\n", sum);}int main(){    freopen("in.txt","r",stdin);    int n,m;    while(scanf("%d%d", &n,&m), n+m)    {        edge E[MAXN];        sum=0;        int i,j;        j=0;        for(i=1; i<=m; i++){            scanf("%d%d%d", &E[j].u,&E[j].v,&E[j].w);            j++;        }        sort(E, E+j, cmd);//按所有边的权值升序排序        kruskal(n, E);    }    return 0;}

感觉会用并查集的话,kruskal算法比较容易理解。。。


0 0