存个模板,顺便复习一下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 }