• 最小生成树


    Kruskal算法

    加边法,初始边数为0,每次选择一条满足条件的最小代价边,加入到最小生成树的边集合里。 

    适用于简单图

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    int n,m,tot=0,k=0;
    int f[200010];
    struct node {
        int from,to,dis;
    }e[200010];
    
    bool cmp(const node &a,const node &b) {
        return a.dis<b.dis;
    }
    
    int getf(int x) {
        return x==f[x]?x:f[x]=getf(f[x]);
    }
    void merge(int x,int y) {
        f[getf(y)]=getf(x);
    }
    int main( ) {
        cin>>n>>m;
        for(int i=1;i<=m;i++) cin>>e[i].from>>e[i].to>>e[i].dis;
        for(int i=1;i<=n;i++) f[i]=i;
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=m;i++)  {
            if(k==n-1) break;
            if(getf(e[i].from)!=getf(e[i].to)) {
                merge(e[i].from,e[i].to);
                tot+=e[i].dis;
                k++;
            }
        }
        cout<<tot<<endl;
        return 0;
    }
    View Code

    Prim算法

    ①选定一个点做为一个集合 a ,剩下的点为另一个集合 b

    ②将横跨两个集合且权重在其中最小的边加入最小生成树

    ③将刚刚加入最小生成树的边中不在集合 a 中的点加入集合 a,直到所有的点加入集合 a

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define maxn 102
    #define inf 1000000
    using namespace std;
    
    int n,m;
    int e[maxn][maxn];
    int dis[maxn],vis[maxn];
    
    void prim() {
        int k=1;
        vis[1]=1;
        for(int i=1;i<=n;i++) dis[i]=e[1][i];
        int pos;
        int sum=0;
        while(k<n) {
            int mini=inf;
            for(int i=1;i<=n;i++) {
                if(!vis[i]&&dis[i]<mini) {
                    mini=dis[i];
                    pos=i;
                }
            }
            vis[pos]=1; k++; sum+=dis[pos];
    
            for(int t=1;t<=n;t++) {
                if(!vis[t]&&dis[t]>e[pos][t]) dis[t]=e[pos][t];
            }
        }
        cout<<sum<<endl;
    }
    
    int main() {
        cin>>n>>m;
        memset(e,0,sizeof(e));
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
            if(i==j) e[i][j]=0;
            else e[i][j]=inf;
    
        int u,v,w;
        for(int i=0;i<m;i++) {
            cin>>u>>v>>w;
            e[u][v]=e[v][u]=w;
        }
        prim();
    
        return 0;
    }
    View Code

    堆优化

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int N=5000+10;
    const int M=200000+10;
    
    int first[N],tot,vis[N],dis[N],n,m;
    priority_queue <P,vector<P>,greater<P> >q;
    struct edge {
        int v,w,net;
    } e[M*2];
    
    void add(int u,int v,int w) {
        e[tot].v=v; e[tot].w=w;
        e[tot].net=first[u];
        first[u]=tot++;
    }
    void prim() {
        int cnt=0,sum=0;
        dis[1]=0;
        q.push(make_pair(0,1));
        while(!q.empty()&&cnt<n) {
            int d=q.top().first,u=q.top().second;
            q.pop();
            if(!vis[u]) {
                cnt++;
                sum+=d;
                vis[u]=1;
                for(int i=first[u]; ~i; i=e[i].net)
                    if(e[i].w<dis[e[i].v]) {
                        dis[e[i].v]=e[i].w;
                        q.push(make_pair(dis[e[i].v],e[i].v));
                    }
            }
        }
        if(cnt==n) printf("%d
    ",sum);
        else puts("orz");
    }
    int main( ) {
        int u,v,w;
        memset(first,-1,sizeof(first));
        memset(dis,0x3f3f3f3f,sizeof(dis));
        tot=0;
        cin>>n>>m;
        for(int i=1; i<=m; i++) {
            cin>>u>>v>>w;
            add(u,v,w);
            add(v,u,w);
        }
        prim();
        return 0;
    }
    View Code
  • 相关阅读:
    BZOJ 1101 [POI2007]Zap
    BZOJ 2005 [Noi2010]能量采集
    BZOJ 1053 [HAOI2007]反素数ant
    BZOJ 4321 queue2
    ZOJ 1456 Minimum Transport Cost(Floyd算法求解最短路径并输出最小字典序路径)
    POJ 3268 Silver Cow Party(Dijkstra算法求解来回最短路问题)
    Trie(字典树)解析及其在编程竞赛中的典型应用举例
    POJ 3037 Skiing(如何使用SPFA求解二维最短路问题)
    POJ 1724 ROADS(使用邻接表和优先队列的BFS求解最短路问题)
    POJ 1860 Currency Exchange(如何Bellman-Ford算法判断图中是否存在正环)
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11562355.html
Copyright © 2020-2023  润新知