luoguP3366 [模板] 最小生成树
Posted frankchen831x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP3366 [模板] 最小生成树相关的知识,希望对你有一定的参考价值。
题目链接:https://www.luogu.org/problemnew/show/P3366
思路:
求最小生成树的模板题,求MST有两种算法——Prim、Kruskal。
两者区别:Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣。Prim是以更新过的节点的连边找最小值,Kruskal是直接将边排序。
两者其实都是运用贪心的思路
我使用的Prim算法(邻接表实现),head是表头结点数组,a是表结点数组,len记录未加入生成树的结点到生成树的最小距离,vis用来记录结点是否加入生成树。
使用邻接表的原因是邻接矩阵虽然耗空间小,但它只能表示边的信息,而不能表示点,所以还需要O(n)的枚举复杂度或比邻接表更多的内存来存储与边相关的信息,
所以使用邻接表的效率更高。
1 #include<bits/stdc++.h> 2 #define R register int 3 using namespace std; 4 5 typedef pair<int,int> PII; 6 struct node{ 7 int v,w,next; 8 }a[400005]; //表结点 9 10 int n,m,k,cnt,sum,x,y,z; 11 int head[5005],len[5005],vis[5005]; 12 priority_queue<PII,vector<PII>,greater<PII> > pq; 13 14 void add(int u,int v,int w){ 15 a[++k].v=v; 16 a[k].w=w; 17 a[k].next=head[u]; 18 head[u]=k; 19 } 20 21 void prim(){ 22 len[1]=0; 23 pq.push(make_pair(0,1)); 24 while(!pq.empty()&&cnt<n){ 25 int l=pq.top().first,m=pq.top().second; 26 pq.pop(); 27 if(!vis[m]){ 28 cnt++; 29 vis[m]=1; 30 sum+=l; 31 for(R i=head[m];i!=-1;i=a[i].next){ 32 if(!vis[a[i].v]&&a[i].w<len[a[i].v]) 33 len[a[i].v]=a[i].w,pq.push(make_pair(a[i].w,a[i].v)); 34 } 35 } 36 } 37 } 38 39 int main(){ 40 memset(head,-1,sizeof(head)); 41 memset(len,0x3f,sizeof(len)); 42 scanf("%d%d",&n,&m); 43 while(m--){ 44 scanf("%d%d%d",&x,&y,&z); 45 add(x,y,z); 46 add(y,x,z); 47 } 48 prim(); 49 if(cnt==n) 50 printf("%d ",sum); 51 else 52 printf("orz "); 53 return 0; 54 }
以上是关于luoguP3366 [模板] 最小生成树的主要内容,如果未能解决你的问题,请参考以下文章