最小生成树模板
Prim算法,O(V^2),适用于稠密图。
1 const int N=1000; 2 const int INF=0x3f3f3f3f; 3 int a[N][N],p[N],low[N];///邻接矩阵 4 int prim(int n) 5 { 6 int i,j,ans=0,poi; 7 memset(p,0,sizeof(p)); 8 p[1]=1; 9 for(i=1;i<=n;i++) 10 low[i]=a[1][i]; 11 for(i=1;i<n;i++) ////n-1次操作 12 { 13 int mi=INF; 14 for(j=1;j<=n;j++) 15 { 16 if(!p[j]&&mi>low[j]) 17 { 18 mi=low[j]; 19 poi=j; 20 } 21 } 22 p[poi]=1; 23 ans+=mi; 24 for(j=1;j<=n;j++) 25 if(!p[j]) 26 low[j]=min(low[j],a[poi][j]); 27 } 28 return ans; 29 }
Kruskal,O(ElogE)。将边按权值从小到大排序,枚举每一条边,若该边的两端不在同一集合中,合并集合。直到找到n-1条边(n为点数)。判断是否在一个集合也可以用并查集做。
1 ////O(ElogE) 适用于稀疏图 2 const int N=1000; 3 const int M=N*N; 4 int p[N]; 5 struct edge 6 { 7 int u,v,w; 8 }e[M]; 9 int cmp(edge a,edge b) 10 { 11 return a.w<b.w; 12 } 13 int kruskal(int n,int m) 14 { 15 sort(e+1,e+m+1,cmp); ////下标从1开始 16 int i,j,k,ans=0,num=0; 17 for(i=1;i<=n;i++) 18 p[i]=i; 19 for(i=1;i<=m&&num<=n-1;i++) 20 { 21 ////判断两端点所在集合 22 for(j=e[i].u;p[j]!=j;j=p[j]) 23 p[j]=p[p[j]]; 24 for(k=e[i].v;p[k]!=k;k=p[k]) 25 p[k]=p[p[k]]; 26 if(j!=k) 27 { 28 p[j]=k; 29 num++; 30 ans+=e[i].w; 31 } 32 } 33 return ans; 34 }