zoukankan      html  css  js  c++  java
  • 模板:最小生成树(MST)

    https://www.luogu.org/problemnew/show/P3366

    Kruskal算法 O(E*logE)
    1. 所有的边从小到大排序
    2. 初始状态下每个结点都是独立的集合
    3. 枚举每一条边e
    4. 如果边的两个端点u、 v属两个不同的集合,
    把这条边加入MST, 否则跳过。
    排序
    贪心选择
    并查集

    用并查集优化后的总时间复杂度为(mlogm+ma(n)),a(n)是一次并查集的复杂度

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 struct Edge{
     6     int u, v, w;
     7 }edge[200005];
     8 int f[5005], n, m, ans, eu, ev, cnt;
     9 inline bool cmp(Edge a,Edge b){ 
    10     return a.w<b.w; 
    11 }
    12 inline int find(int x){
    13     while(x!=f[x]) x=f[x]=f[f[x]];
    14     return x;
    15 }
    16 int main(){
    17     scanf("%d%d",&n,&m);
    18     for(int i=1; i<=n; i++) f[i]=i;
    19     for(int i=0; i<m; i++)
    20         scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    21     sort(edge, edge+m, cmp);
    22     for(int i=0; i<m; i++){
    23         eu=find(edge[i].u);
    24         ev=find(edge[i].v);
    25         if(eu==ev) continue;
    26         ans+=edge[i].w;
    27         f[ev]=eu; 
    28         cnt++;
    29         if(cnt==n-1) break;
    30     }
    31     printf("%d",ans);
    32     return 0;
    33 }

     Prim算法 O(N^2)
    加点法, 每次选择代价最小的边对应的点,
    加入到最小生成树中。
    算法从某一个顶点s开始, 逐渐长大覆盖整
    个连通网的所有顶点。
    1. 图顶点集合为V; 初始集合u={s},v=V-u
    2. 在两个集合u,v能够组成的边中, 选择一条
    代价最小的边(u0,v0), 加入到最小生成树
    中, 并把v0并入到集合u中。
    3. 重复上述步骤, 直到最小生成树有n-1条边
    或者n个顶点为止。

    此处使用堆优化的的prim,每次选取最小值的时间复杂度为O(logm),总时间复杂度为O((n+m)logm).

     1 #include<cstdio>
     2 #include<queue>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef pair <int,int> pii;
     7 int k, n, m, cnt, sum,x, y, z;
     8 int h[5005], dis[5005], vis[5005];
     9 struct Edge{
    10     int v, w, next;//边的右端点, 边权, 下一条边的编号 
    11 }e[400005];
    12 void add(int u,int v,int w){
    13     e[++k].v=v;
    14     e[k].w=w;
    15     e[k].next=h[u];
    16     h[u]=k;
    17 }
    18 priority_queue <pii,vector<pii>,greater<pii> > q;//第一维数值,第二维节点编号 
    19 void prim(){
    20     dis[1]=0;
    21     q.push(make_pair(0,1));
    22     while(!q.empty() && cnt<n){
    23         int d=q.top().first, u=q.top().second;
    24         q.pop();
    25         if(vis[u]) continue;
    26         cnt++;
    27         sum+=d;
    28         vis[u]=1;
    29         for(int i=h[u]; i!=-1; i=e[i].next)
    30             if(e[i].w<dis[e[i].v]){ 
    31                 dis[e[i].v]=e[i].w;
    32                 q.push(make_pair(dis[e[i].v],e[i].v));
    33             } 
    34     }
    35 }
    36 int main(){
    37     memset(dis,0x3f,sizeof(dis));
    38     memset(h,-1,sizeof(h));
    39     scanf("%d%d",&n,&m);
    40     for(int i=1; i<=m; i++){
    41         scanf("%d%d%d",&x,&y,&z);
    42         add(x,y,z);
    43         add(y,x,z);
    44     }
    45     prim();
    46     if(cnt==n)    printf("%d",sum);
    47     else         printf("orz");
    48     return 0;
    49 }
    "Hello World!"
  • 相关阅读:
    [转]人生哲理小故事
    取PE文件OriginalFilename解析VERSION资源
    [转]COM对象创建外部机制
    读书的几个步骤
    zoj 2412 Farm Irrigation
    HDU 1575 Tr A
    toj 2843 Diamonds
    HDU 1856 More is better
    toj 2841 Bitwise Reverse
    hdu 1213 How Many Tables
  • 原文地址:https://www.cnblogs.com/Aze-qwq/p/9337735.html
Copyright © 2011-2022 走看看