最小生成树
Kruskal算法
加边法,初始边数为0,每次选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
适用于简单图
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; int n,m,tot=0,k=0; int f[200010]; struct node { int from,to,dis; }e[200010]; bool cmp(const node &a,const node &b) { return a.dis<b.dis; } int getf(int x) { return x==f[x]?x:f[x]=getf(f[x]); } void merge(int x,int y) { f[getf(y)]=getf(x); } int main( ) { cin>>n>>m; for(int i=1;i<=m;i++) cin>>e[i].from>>e[i].to>>e[i].dis; for(int i=1;i<=n;i++) f[i]=i; sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++) { if(k==n-1) break; if(getf(e[i].from)!=getf(e[i].to)) { merge(e[i].from,e[i].to); tot+=e[i].dis; k++; } } cout<<tot<<endl; return 0; }
Prim算法
①选定一个点做为一个集合 a ,剩下的点为另一个集合 b
②将横跨两个集合且权重在其中最小的边加入最小生成树
③将刚刚加入最小生成树的边中不在集合 a 中的点加入集合 a,直到所有的点加入集合 a
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 102 #define inf 1000000 using namespace std; int n,m; int e[maxn][maxn]; int dis[maxn],vis[maxn]; void prim() { int k=1; vis[1]=1; for(int i=1;i<=n;i++) dis[i]=e[1][i]; int pos; int sum=0; while(k<n) { int mini=inf; for(int i=1;i<=n;i++) { if(!vis[i]&&dis[i]<mini) { mini=dis[i]; pos=i; } } vis[pos]=1; k++; sum+=dis[pos]; for(int t=1;t<=n;t++) { if(!vis[t]&&dis[t]>e[pos][t]) dis[t]=e[pos][t]; } } cout<<sum<<endl; } int main() { cin>>n>>m; memset(e,0,sizeof(e)); memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i==j) e[i][j]=0; else e[i][j]=inf; int u,v,w; for(int i=0;i<m;i++) { cin>>u>>v>>w; e[u][v]=e[v][u]=w; } prim(); return 0; }
堆优化
#include <iostream> #include <queue> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; typedef pair<int,int> P; const int N=5000+10; const int M=200000+10; int first[N],tot,vis[N],dis[N],n,m; priority_queue <P,vector<P>,greater<P> >q; struct edge { int v,w,net; } e[M*2]; void add(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].net=first[u]; first[u]=tot++; } void prim() { int cnt=0,sum=0; dis[1]=0; q.push(make_pair(0,1)); while(!q.empty()&&cnt<n) { int d=q.top().first,u=q.top().second; q.pop(); if(!vis[u]) { cnt++; sum+=d; vis[u]=1; for(int i=first[u]; ~i; i=e[i].net) if(e[i].w<dis[e[i].v]) { dis[e[i].v]=e[i].w; q.push(make_pair(dis[e[i].v],e[i].v)); } } } if(cnt==n) printf("%d\n",sum); else puts("orz"); } int main( ) { int u,v,w; memset(first,-1,sizeof(first)); memset(dis,0x3f3f3f3f,sizeof(dis)); tot=0; cin>>n>>m; for(int i=1; i<=m; i++) { cin>>u>>v>>w; add(u,v,w); add(v,u,w); } prim(); return 0; }