• 【模板】最小生成树 [最小生成树][prim kruskal]


    prim

    1. 先建立一个只有一个结点的树,这个结点可以是原图中任意的一个结点
    2. 使用一条边扩展这个树,要求这条边一个顶点在树中另一个顶点不在树中,并且这条边的权值要求最小。
    3. 重复步骤2直到所有顶点都在树中

    又双叒叕看学长的模板写的 顺便重新感性理解优先队列

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define rg register
    const int N=1000+5,M=1000000+5,inf=0x3f3f3f3f,P=19650827;
    int n,m;
    ll ans=0;
    typedef pair<int,int>pii;                        //pair
    priority_queue<pii,vector<pii>,greater<pii> >q; //小顶堆 
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    int tot=0,head[N];
    struct edge{int v,nxt,w;}e[M<<1];
    void add(int u,int v,int w){
        e[++tot]=(edge){v,head[u],w};head[u]=tot;
    }
    
    int dis[N],vis[N];
    void prim(){
        memset(vis,0,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        q.push(make_pair(dis[1]=0,1));
        while(!q.empty()){
            int u=q.top().second;q.pop();
            if(vis[u]) continue;
            ans+=dis[u],vis[u]=1;
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].v,w=e[i].w;
                if(!vis[v]&&dis[v]>w){
                    dis[v]=w;
                    q.push(make_pair(dis[v],v));
                }
            }
        }
    }
    int main(){
        rd(n),rd(m);
        int u,v,w;
        for(rg int i=1;i<=m;++i){
            rd(u),rd(v),rd(w);
            add(u,v,w),add(v,u,w);
        }
        prim();
        printf("%lld",ans);
        return 0;
    }
     

    P3366 【模板】最小生成树   加一个cnt来记录加了多少个点 最后不足n个则表明没有连通

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<stack>
     7 #include<algorithm>
     8 using namespace std;
     9 #define ll long long
    10 #define rg register
    11 const int N=5000+5,M=200000+5,inf=0x3f3f3f3f,P=19650827;
    12 int n,m;
    13 ll ans=0;
    14 typedef pair<int,int>pii;                        //pair
    15 priority_queue<pii,vector<pii>,greater<pii> >q; //小顶堆 
    16 template <class t>void rd(t &x){
    17     x=0;int w=0;char ch=0;
    18     while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    19     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    20     x=w?-x:x;
    21 }
    22 
    23 int tot=0,head[N];
    24 struct edge{int v,nxt,w;}e[M<<1];
    25 void add(int u,int v,int w){
    26     e[++tot]=(edge){v,head[u],w};head[u]=tot;
    27 }
    28 
    29 int dis[N],vis[N],cnt=0;
    30 bool prim(){
    31     memset(vis,0,sizeof(vis));
    32     memset(dis,inf,sizeof(dis));
    33     q.push(make_pair(dis[1]=0,1));
    34     while(!q.empty()){
    35         int u=q.top().second;q.pop();
    36         if(vis[u]) continue;
    37         ans+=dis[u],vis[u]=1,++cnt;
    38         for(int i=head[u];i;i=e[i].nxt){
    39             int v=e[i].v,w=e[i].w;
    40             if(!vis[v]&&dis[v]>w){
    41                 dis[v]=w;
    42                 q.push(make_pair(dis[v],v));
    43             }
    44         }
    45     }
    46     if(cnt!=n) return 0;
    47     else return 1;
    48 }
    49 int main(){
    50     rd(n),rd(m);
    51     int u,v,w;
    52     for(rg int i=1;i<=m;++i){
    53         rd(u),rd(v),rd(w);
    54         add(u,v,w),add(v,u,w);
    55     }
    56     if(!prim()) printf("orz");
    57     else printf("%lld",ans);
    58     return 0;
    59 }
    60  
    3366 prim
    /*prim
    */
    #include<cstdio>
    #include<iostream>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N=1000001,M=1000001,inf=1e9;
    int n,m,o,hd[N],dis[N],vis[N];
    typedef pair<int,int>pii;                        //pair
    priority_queue<pii,vector<pii>,greater<pii> >q; //小顶堆 
    struct Edge{int v,nt,w;}E[M<<1];
    int main()
    {//    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        scanf("%d%d",&n,&m);
        o=1;
        for(int i=1;i<=n;i++)dis[i]=inf;
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            E[o]=(Edge){v,hd[u],w}; hd[u]=o++;
            E[o]=(Edge){u,hd[v],w}; hd[v]=o++;
        }
        q.push(make_pair(dis[1]=0,1));
        ll ans=0;
        while(!q.empty()){
            int u=q.top().second; q.pop();//记得pop! 
            if(vis[u])continue;
            vis[u]=1;
            ans+=dis[u];
            for(int i=hd[u];i;i=E[i].nt){
                int v=E[i].v;
                if(!vis[v]&&dis[v]>E[i].w){//和dijkstra不同! 
                    dis[v]=E[i].w;
                    q.push(make_pair(dis[v],v));
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }//by tkys_Austin;
    学长's

    kruskal

    1. 将边按照边权从小到大排序,并建立一个没有边的图T
    2. 选出一条没有被选过的边权最小的边。
    3. 如果这条边两个顶点在T中所在的连通块不相同,那么将它加入图T
    4. 重复2和3直到图T连通为止。

    由于只需要维护连通性,可以不需要真正建立图T,可以用并查集来维护

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define rg register
    const int N=1000+5,M=1000000+5,inf=0x3f3f3f3f,P=19650827;
    int n,m,cnt=0,f[N];
    ll ans=0;
    
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    struct edge{
        int u,v,w;
        bool operator<(const edge&A)const{return w<A.w;}
    }e[M];
    int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    
    void kruskal(){
        for(rg int i=1;i<=n;++i) f[i]=i;
        for(rg int i=1,u,v;i<=m;++i){
            u=e[i].u,v=e[i].v;
            if(find(u)!=find(v)){
                f[f[u]]=f[v];
                ans+=e[i].w;
            }
        }
    }
    
    int main(){
        rd(n),rd(m);
        for(int i=1,u,v,w;i<=m;++i){
            rd(u),rd(v),rd(w);
            e[i]=(edge){u,v,w};
        }
        sort(e+1,e+1+m);
        kruskal();
        printf("%lld",ans);
        return 0;
    }
     
    /*kruskal
    */ 
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1000001,M=1000001;
    int n,m,f[N],cnt; 
    struct edge{
        int u,v,w;
        bool operator<(const edge&A)const{
            return w<A.w;
        }
    }e[M];
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    int main()
    {    freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        scanf("%d%d",&n,&m);
        ll ans=0;
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            e[++cnt]=(edge){u,v,w};
        }
        sort(e+1,e+cnt+1);
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1,u,v;i<=m;i++){
            u=e[i].u; v=e[i].v;
            if(find(u)!=find(v)){
                f[f[u]]=f[v];
                ans+=e[i].w;
            }
        }
        cout<<ans<<endl;
        return 0;
    }//by tkys_Austin;
    学长's
  • 相关阅读:
    自动配置原理5
    JSR303数据校验4
    mysql 安装(压缩包安装和exe安装)
    jQuery关于复制(复制隐藏文字+显示文字)跳转,Clipboard
    html页面设置一个跟随鼠标移动的DIV(jQuery实现)
    js中将时间(如:2017-10-8 22:44:55)转化为时间搓,时间戳转为标准格式时间
    异常:java.lang.IllegalArgumentException: Control character in cookie value or attribute.
    从数据库导出数据到excel之List<List<Object>>导出
    从数据库导出数据到excel之List<map>导出
    从数据库导出数据到excel之POI操作
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/10926724.html
Copyright © 2020-2023  润新知