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 }
  • 相关阅读:
    Using Resource File on DotNet
    C++/CLI VS CSharp
    JIT VS NGen
    [Tip: disable vc intellisense]VS2008 VC Intelisense issue
    UVa 10891 Game of Sum(经典博弈区间DP)
    UVa 10723 Cyborg Genes(LCS变种)
    UVa 607 Scheduling Lectures(简单DP)
    UVa 10401 Injured Queen Problem(简单DP)
    UVa 10313 Pay the Price(类似数字分解DP)
    UVa 10635 Prince and Princess(LCS N*logN)
  • 原文地址:https://www.cnblogs.com/cervusy/p/9756262.html
Copyright © 2011-2022 走看看