• 最小生成树模板


      prim算法:

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 900000r
    #define N 1000
    int n,m;
    int ans;
    int mp[N][N];
    int vis[N];
    struct edge
    {
        int to;//to为通向的边
        int v;//为权值
        friend bool operator<(const edge& a,const edge& b)
        {
            return a.v>b.v;
        }
    }now;
    
    void prim(int s)
    {
        vis[s]=1;
        priority_queue<edge>q;
        while(!q.empty())q.pop();
    
        rep(i,1,n)
        {
            rep(j,1,n)
            if(!vis[j])
            {
                now.to=j;
                now.v=mp[s][j];
                q.push(now);
            }
            while(!q.empty()&&vis[q.top().to])
                q.pop();
            if(q.empty())break;
            now=q.top();q.pop();
            s=now.to;
            ans+=now.v;
            vis[s]=1;
        }
    }
    
    int main()
    {
        CLR(vis,0);
        RII(n,m);
        rep(i,1,n)
        rep(j,1,n)
        mp[i][j]=inf;
        while(m--)
        {
            int a,b,c;
            RIII(a,b,c);
            a++;b++;
            mp[a][b]=mp[b][a]=c;
        }
        prim(1);
        cout<<ans<<endl;
        return 0;
    }
    View Code

    之前貌似学了假的prim   

    下面给出更加普遍的写法  和dijkstra非常相似。。。  

        rep(i,1,n)
        dis[i]=inf;
        dis[1]=0;int u;
        rep(i,1,n)
        {
            double minn=1e8;
            rep(j,1,n)
            if(!vis[j]&&dis[j]<minn)
            minn=dis[u=j];
            ans+=minn;
            vis[u]=1;
            rep(j,1,n)
                if(dis[u]<dis[j])dis[j]=dis[u];
        }
    View Code

    prim:该算法的时间复杂度为O(n2)。与图中边数无关,该算法适合于稠密图。

    kruskal:需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。适合稀疏图。

    第一个prim是经过堆优化过的   

    其实并没有优化多少  只要记得稠密图用prim  稀疏图用kruskal即可

    kruskal  注意一定要大一点的数组

    struct node
    {
        int s,e,v;
    }s[100005];
    int f[N];
    int n,m;
    int find1(int x)
    {
      return f[x]==x?x:find1(f[x]);
    }
    bool cmp(node a,node b)
    {
        return a.v<b.v;
    }
    int kruskal()
    {
        int a,b,x=1;//一开始一定要是1
        int ans=0;
        sort(s+1,s+1+m,cmp);
        rep(i,1,m)
        {
            int a=find1(s[i].s);
            int b=find1(s[i].e);
            if(a==b)continue;
            ans+=s[i].v;
            f[a]=b;
            x++;
            if(x==n)return ans;//遍历了所有的点 是时候退出了
        }
        if(x!=n)return -1;//说明没有最小生成树
        else return ans;
    }
    
    
    int main()
    {
        RII(n,m);
        rep(i,1,n)
        f[i]=i;
        rep(i,1,m)
        RIII(s[i].s,s[i].e,s[i].v);
        printf("%d
    ",kruskal());
    }
    View Code
  • 相关阅读:
    针对数据库开发人员的性能调优小提示
    Oracle EBS 12 目录结构
    程序集反射
    DataTable.Select() 返回DataTable结果
    有趣的23中设计模式
    『原创』用C++开发WM应用系列(5)——接触ListBox控件
    『原创』用C++开发WM应用系列(1)——"Hello World" Pro!(上)
    【参考】在PPC上面检查文件MD5
    用C++开发WM应用系列文章索引
    『原创』用C++开发WM应用系列(1)——"Hello World" Pro!(下)
  • 原文地址:https://www.cnblogs.com/bxd123/p/10560965.html
Copyright © 2020-2023  润新知