zoukankan      html  css  js  c++  java
  • [洛谷P3366] [模板] 最小生成树

    存个模板,顺便复习一下kruskal和prim。

    题目传送门

    kruskal

    稀疏图上表现更优。

    设点数为n,边数为m。

    复杂度:O(mlogm)。

    先对所有边按照边权排序,初始化并查集的信息。

    然后枚举每一条边,如果当前边的两个端点不在一个并查集里,就选上这条边。

    如果图不连通会造成选的边数小于n-1。

    如果成功生成了最小生成树,就会正好选n-1条边(树的性质)。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 
     7 int n,m,cnt,ans;
     8 
     9 struct edge
    10 {
    11     int x,y,w;
    12 }e[200005];
    13 
    14 int f[5005];
    15 
    16 int findfa(int p)
    17 {
    18     if(p==f[p])return p;
    19     f[p]=findfa(f[p]);
    20     return f[p];
    21 }
    22 
    23 int cmp(edge q,edge r)
    24 {
    25     return q.w<r.w;
    26 }
    27 
    28 void kruskal()
    29 {
    30     sort(e+1,e+m+1,cmp);
    31     for(int i=1;i<=m;i++)
    32     {
    33         int fx=findfa(e[i].x);
    34         int fy=findfa(e[i].y);
    35         if(fx==fy)continue;
    36         ans+=e[i].w;
    37         cnt++;
    38         f[fx]=fy;
    39     }
    40 }
    41 
    42 int main()
    43 {
    44     scanf("%d%d",&n,&m);
    45     for(int i=1;i<=n;i++)f[i]=i;
    46     for(int i=1;i<=m;i++)
    47         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
    48     kruskal();
    49     if(cnt<n-1)printf("orz");
    50     else printf("%d",ans);
    51     return 0;
    52 }

    prim

    稠密图上表现更优。

    时间复杂度:O(nlogn+m)。

    算法很像dijkstra求最短路。

    只不过这个是维护某个点到已选的点组成的点集的距离,而不是到源点的距离。

    初始先随便选一个点,把这个点的距离设为0,剩下的点的距离设为0x3f3f3f3f。

    然后就很像dijkstra......

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 
     7 int n,m,cnt,ans;
     8 int hd[5005],nx[400005],to[400005],len[400005],ec;
     9 int dis[5005],v[5005];
    10 
    11 void edge(int af,int at,int ev)
    12 {
    13     to[++ec]=at;
    14     nx[ec]=hd[af];
    15     len[ec]=ev;
    16     hd[af]=ec;
    17 }
    18 
    19 struct data
    20 {
    21     int ps,ds;
    22     friend bool operator<(data q,data w)
    23     {
    24         return q.ds>w.ds;
    25     }
    26 };
    27 
    28 priority_queue<data>qq;
    29 
    30 void prim()
    31 {
    32     memset(dis,0x3f,sizeof(dis));
    33     dis[1]=0,cnt++;
    34     qq.push((data){1,0});
    35     while(!qq.empty()&&cnt<=n)
    36     {
    37         data p=qq.top();
    38         qq.pop();
    39         if(v[p.ps])continue;
    40         v[p.ps]=1;
    41         cnt++;
    42         ans+=p.ds;
    43         for(int i=hd[p.ps];i;i=nx[i])
    44         {
    45             if((dis[to[i]]>len[i])&&(!v[to[i]]))
    46             {
    47                 dis[to[i]]=len[i];
    48                 qq.push((data){to[i],dis[to[i]]});
    49             }
    50         }
    51     }
    52 }
    53 
    54 int main()
    55 {
    56     scanf("%d%d",&n,&m);
    57     for(int i=1;i<=m;i++)
    58     {
    59         int x,y,z;
    60         scanf("%d%d%d",&x,&y,&z);
    61         edge(x,y,z);
    62         edge(y,x,z);
    63     }
    64     prim();
    65     if(cnt<n)printf("orz");
    66     else printf("%d",ans);
    67     return 0;
    68 }
  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/cervusy/p/9756262.html
Copyright © 2011-2022 走看看