zoukankan      html  css  js  c++  java
  • 模板——最小生成树prim算法&&向前星理解

    通过最小生成树(prim)和最短路径优化引出的向前星存图,时至今日才彻底明白了。。

    head[i]存储的是父节点为i引出的最后一条边的编号

    next负责把head[i]也就是i作为父节点的所有边连接起来,next也是存的编号

    在所存的edge结构体中,只有w是保存边的值,而u是保存的子节点。

    这样设置的话,由head[i]就可以引出所有与i相关的边和点,

    显而易见,这样的存放方法空间+时间复杂度双优化,比邻接矩阵是优化多了。。

    然后就是prim算法,

    最小生成树的一种算法,适用于稠密图,因为是以点更新的,正好与之前的克鲁斯卡尔算法互补了,

    不过代码比k长,思路也难一些,大致和迪杰差不多,也用了dis数组,目测也就是更新dis值的时候不同(其实很不同,就形式差不多而已)

    下面附上代码,借鉴某位luogu大神的题解,真的很简洁明了了,在luogu上比 k 快了大概一倍240+ms。

    其他优化用了快读+re。

     1 #include <iostream>
     2 #include <string>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 #define maxn 5002
     7 #define maxm 200001
     8 #define inf 9999
     9 #define re register
    10 
    11 using namespace std;
    12 
    13 int n,m,cnt,sum=0,k=0;
    14 int a,b,c;
    15 int dis[maxn],head[maxn],vis[maxn];
    16 
    17 typedef pair <int,int> pii;
    18 priority_queue <pii,vector<pii>,greater<pii> > q;
    19 
    20 struct Edge
    21 {
    22     int w,next,v;//w权值,v子节点 
    23 }edge[maxm*2];
    24 inline int read()  
    25 {  
    26     char ch;  
    27     int a=0;  
    28     while(!(((ch=getchar())>='0')&&(ch<='9')));  
    29     a*=10;a+=ch-'0';  
    30     while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';  
    31     return a;  
    32 }
    33 void add(int u,int v,int w)
    34 {
    35     edge[++cnt].v=v;
    36     edge[cnt].w=w;
    37     edge[cnt].next =head[u];
    38     head[u]=cnt; 
    39 }
    40 
    41 void prim()
    42 {
    43     dis[1]=0;
    44     q.push(make_pair(0,1));
    45     while(!q.empty()&&k<n)
    46     {
    47         int d=q.top().first,u=q.top().second;//first 最小值,second 位置  
    48         q.pop();
    49         if(vis[u])continue;
    50         k++;
    51         sum+=d;
    52         vis[u]=1;
    53         for(re int i=head[u];i!=-1;i=edge[i].next )
    54         {
    55             if((edge[i].w<dis[edge[i].v]))
    56             {
    57                 dis[edge[i].v]=edge[i].w;
    58                 q.push(make_pair(dis[edge[i].v],edge[i].v)) ;
    59             }
    60         }
    61     } 
    62 }
    63 
    64 int main()
    65 {
    66     memset(head,-1,sizeof(head));
    67     memset(dis,inf,sizeof(dis));
    68     n=read();
    69     m=read();
    70     for(re int i=1;i<=m;i++)
    71     {
    72         a=read();b=read();c=read();
    73         add(a,b,c);
    74         add(b,a,c);
    75     }
    76     prim();
    77     if(k==n)printf("%d",sum);
    78     else  cout<<"orz";
    79     return 0;
    80 }
    ———————————————————————————————— 执笔饰年华,一笑叹天涯。逢春即润物,生当得潇洒。
  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/SuperGoodGame/p/9072746.html
Copyright © 2011-2022 走看看