最小生成树是指带权图中连接图中所有顶点的权值最小的生成树。
这里有两种比较大众化的算法:Prime算法和kruskal算法
我们先来介绍一下Prime算法,Prime算法的核心是贪心,先把图某一顶点加入点集V中,然后开始遍历与该点集中的点相邻的边中的权值最小的边所相连的点,再把这点加入点集V中,直至点集V包含图中的所有顶点为止,可以看出,他的复杂度是O(n^2)
代码如下:
#include <cstdio> #include <cstring> #include <iostream> #define MAX 100 #define INF 999999999 using namespace std; bool s[MAX]; int map[MAX][MAX],dist[MAX]; void init(int n) { int i,j; memset(s,false,sizeof(s)); for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=INF; for(i=1;i<=n;i++) map[i][i]=0; } int Prime(int n) { int i,j,k,mind,sum; for(i=1;i<=n;i++) dist[i]=map[1][i]; s[1]=true; sum=0; for(i=1;i<=n;i++) { mind=INF; k=1; for(j=1;j<=n;j++) if(!s[j]&&dist[j]<mind) { mind=dist[j]; k=j; } s[k]=true; sum+=dist[k]; for(j=1;j<=n;j++) if(!s[j]&&dist[j]>map[k][j]) dist[j]=map[k][j]; } return sum; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=-1) { init(n); int a,b,x; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&x); map[a][b]=map[b][a]=x; } printf("%d\n",Prime(n)); } return 0; }
Kruskal算法:
Kruskal算法又称为避圈法,顾名思义,就是避开回路和环。其算法思想是先把图中各边按权值由小到大排列,拿出权值最小的边作为一个新的集合,不断从剩下的边集中取出当前权值最小的且和已选边集不构成回路的边,然后加入当前集合中,对于一个有m个顶点n条边的图来说,当边集中的边的个数为n-1时跳出循环即可。
代码实现如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define MAX 1000 typedef struct node { int from,to; int w; }Node;//前向星表示图 Node map[MAX*MAX]; int n,m;//n代表边数,m代表顶点数 //并查集部分 int par[MAX],rank[MAX]; void Init() { for(int i=1;i<=n;i++) { par[i]=i; rank[i]=1; } } int Find(int x) { if(par[x]!=x) return par[x]=Find(par[x]); return par[x]; } void Union(int x,int y) { x=Find(x); y=Find(y); if(x==y) return ; if(rank[x]>rank[y]) { par[y]=x; rank[x]+=rank[y]; } else { par[x]=y; rank[y]+=rank[x]; } } //Kruskal算法求最小生成树 int cmp(const Node &a,const Node &b) { return a.w<b.w; } int Kruskal() { Init(); int sum=0,k=0; sort(map+1,map+1+m,cmp); for(int i=1;i<=m;i++) { if(k==n-1) break; int x=Find(map[i].from); int y=Find(map[i].to); if(x!=y) { Union(x,y); sum+=map[i].w; k++; } } return sum; } int main() { while(scanf("%d%d",&n,&m)!=-1) { int a,b,x; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&x); map[i].from=a; map[i].to=b; map[i].w=x; } printf("%d\n",Kruskal()); } return 0; }
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=1233
http://acm.hdu.edu.cn/showproblem.php?pid=1863
http://acm.hdu.edu.cn/showproblem.php?pid=1102