prim算法

最小生成树:

1.生成树中任意顶点之间有且仅有一条通路,也就是说,生成树中不能存在回路;

2.对于具有 n 个顶点的连通网,其生成树中只能有 n-1 条边,这 n-1 条边连通着 n 个顶点。

朴素版prim算法

一:适用范围

稠密图,时间复杂度O(n2

二:算法思路

1.所有距离初始化为正无穷

2.n次迭代

  1.找到集合外距离最近的点t

  2.用t更新其他点到集合的距离

  3.把t加入到集合中去

 

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=510,INF=0x3f3f3f3f;
int g[N][N],dist[N],st[N];
int n,m;
int  prim()
{
    int res=0;
    memset(dist,0x3f,sizeof dist);
    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!st[j]&&(t==-1||dist[t]>dist[j])) t=j;
        if(i&&dist[t]==INF) return INF;
        if(i) res+=dist[t];
        for(int j=1;j<=n;j++) dist[j]=min(dist[j],g[t][j]);
        st[t]=1;
    }
    return res;
}
int main()
{
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    while(m--)
    {
        int u,v,w;
        cin>>u>>v>>w;
        g[u][v]=g[v][u]=min(g[u][v],w);
    }
    int t=prim();
    if(t==INF) puts("impossible");
    else cout<<t<<endl;
    return 0;
}

  

kruskal算法

一:适用范围

稀疏图,时间复杂度O(eloge)

二:算法思路

1.将所有边按权重从小到大排序(sort) O(mlogm)

2.枚举每条边a,b,权重c .

  如果a,b不连通,将这条边加入到集合中去.

#include<iostream>
#include<algorithm>
using namespace std;
const int N=200010;
int n,m;
int p[N];
struct Edge
{
    int a,b,w;
    bool operator<(const Edge&W)const
    {
        return w<W.w;
    }
}edges[N];
int find(int x)
{
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        edges[i]={u,v,w};
    }
    sort(edges,edges+m);
    for(int i=1;i<=n;i++) p[i]=i;
    int res=0,cnt=0;
    for(int i=0;i<m;i++)
    {
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=find(a),b=find(b);
        if(a!=b)
        {
            p[a]=b;
            res+=w;
            cnt++;
        }
    }
    if(cnt<n-1) puts("impossible");
    else cout<<res<<endl;
    return 0;
}

  

posted @ 2021-08-06 22:53  Mrr-  阅读(68)  评论(0)    收藏  举报