zoukankan      html  css  js  c++  java
  • 最小生成树-Prim&Kruskal

    Prim算法

    算法步骤

    S:当前已经在联通块中的所有点的集合
    1. dist[i] = inf
    2. for n 次
        t<-S外离S最近的点
        利用t更新S外点到S的距离
        st[t] = true
    n次迭代之后所有点都已加入到S中
    联系:Dijkstra算法是更新到起始点的距离,Prim是更新到集合S的距离

    算法复杂度

    O(n2

    代码

    题目:https://www.acwing.com/problem/content/description/860/

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=550,INF=0x3f3f3f3f;
    int n,m;
    int dist[N];
    int g[N][N];
    bool st[N];
    
    int prim()
    {
        int ans=0;
        memset(dist,0x3f,sizeof(dist));
        int i,j;
        for(i=0;i<n;i++)
        {
            int t=-1;
            for(j=1;j<=n;j++)
            {
                if(!st[j]&&(t==-1||dist[t]>dist[j]))
                    t=j;
            }
            //如果不是第一个点,并且距离为INF,代表不联通
            if(i&&dist[t]==INF)
                return INF;
            //非第一个点,且联通,将点加入,一定要先加入后更新
            if(i)
                ans+=dist[t];
            //如果先更新,则会出现g[t][t]小于dist[j],会出现自环
            for(j=1;j<=n;j++)
                dist[j]=min(dist[j],g[t][j]);
            //标记到集合
            st[t]=true;
        }
        return ans;
    }
    
    int main()
    {
        int i,j;
        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;
        return 0;
    }

    Kruskal算法

    算法步骤

     代码

    题目:https://www.acwing.com/problem/content/description/861/

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int n,m;
    int p[N];
    
    struct node
    {
        int u,v,w;
        bool operator< (const node &W)const
        {
            return w<W.w;
        }
    }edges[N];
    
    int find(int x)
    {
        if(p[x]!=x)
            p[x]=find(p[x]);
        return p[x];
    }
    
    int main()
    {
        int i,j;
        cin>>n>>m;
        for(i=0;i<m;i++)
        {
            int u,v,w;
            cin>>u>>v>>w;
            edges[i]={u,v,w};
        }
        //排序
        sort(edges,edges+m);
        //初始化
        for(i=0;i<n;i++)
            p[i]=i;
        //记录边权值和,边数
        int cnt=0;
        int ans=0;
        for(i=0;i<m;i++)
        {
            int u,v,w;
            u=edges[i].u,v=edges[i].v,w=edges[i].w;
            //找到对应的祖先
            int a=find(u);
            int b=find(v);
            //若不在一个集合,就归入
            if(a!=b)
            {
                ans+=w;
                cnt++;
                //指定的是u,v的祖先,归一
                p[a]=b;
            }
        }
        //若不为n-1条边,则代表不联通
        if(cnt<n-1)
            cout<<"impossible";
        else
            cout<<ans;
        return 0;
    }
  • 相关阅读:
    [恢]hdu 1548
    [恢]hdu 2102
    [恢]hdu 1238
    [恢]hdu 2564
    [恢]hdu 2565
    关于mmu,bootloader,dta以及各种乱七八糟
    总有那些让人XX的词语
    VS2005+SQL2005 Reporting Service动态绑定报表(Web)
    (已测试)在本地处理模式下将数据库数据源与 ReportViewer Web 服务器控件一起使用
    如何在单台计算机上安装 Reporting Services
  • 原文地址:https://www.cnblogs.com/xiaofengzai/p/14374289.html
Copyright © 2011-2022 走看看