模板——最小生成树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 }

 

posted @ 2018-05-22 16:33  SuperGoodGame  阅读(236)  评论(0编辑  收藏  举报