一:Prim算法(适合边多的稠密图)
#include<cstdio>
using namespace std;
const int maxn=30;
const int INF=1000000;
int graph[maxn][maxn];
int lowcost[maxn],closet[maxn];/*lowcost表示每个点的最小花费;closet表示最小花费对应相连的点*/
int visited[maxn];/*visited区分两个集合*/
int n;/*n个点*/
void createGraph(){
memset(graph,0,sizeof(graph));
memset(lowcost,0,sizeof(lowcost));
memset(closet,0,sizeof(closet));
memset(visited,0,sizeof(visited));
int a;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&a);
if(a==0)
graph[i][j]=graph[j][i]=INF;
else
graph[i][j]=graph[j][i]=a;
}
}
void prim(){
int sum=0;
visited[0]=1;/*选中第一个点*/
for(int i=0;i<n;i++){
lowcost[i]=graph[i][0];/*每个点与第一个点的权值*/
closet[i]=0;/*与i点相连的是第一个点*/
}
for(int i=1;i<n;i++){ /*剩下n-1个点*/
int minn=lowcost[0],k=0;
for(int j=0;j<n;j++){
if(!visited[j] && lowcost[j]<minn){
minn=lowcost[j];
k=j;
}
}
sum+=minn;
visited[k]=1;
for(int t=0;t<n;t++){ /*松弛操作*/
if(!visited[t] && lowcost[t]>graph[t][k]){
lowcost[t]=graph[t][k];
closet[t]=k;
}
}
}
printf("%d\n",sum);
}
int main()
{
// freopen("input.txt","r",stdin);
while(~scanf("%d",&n)){
if(!n) break;
createGraph();
prim();
}
}
二:Kruskal算法(适合边少的稀疏图)
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN = 30; /*结点数目上限*/
int pa[MAXN]; /*pa[x]表示x的父节点*/
int rank[MAXN]; /*rank[x]是x的高度的一个上界*/
int n,sum;/*n个点;sum存储最小生成树的总权重 */
struct node{
int x,y;
int w;
}edge[MAXN*MAXN];
bool cmp(node p,node q){
return p.w<q.w;
}
/*创建一个单元集*/
void make_set(int x)
{
pa[x] = x;
rank[x] = 0;
}
/*带路径压缩的查找*/
int find_set(int x)
{
if(x != pa[x])
pa[x] = find_set(pa[x]);
return pa[x];
}
/*按秩合并x,y所在的集合*/
void union_set(int x, int y,int w)
{
x = find_set(x);
y = find_set(y);
if(x == y)return ;
if(rank[x] > rank[y])/*让rank比较高的作为父结点*/
{
pa[y] = x;
}
else
{
pa[x] = y;
if(rank[x] == rank[y])
rank[y]++;
}
sum+=w;
}
int main()
{
// freopen("input.txt","r",stdin);
while(cin>>n){
if(!n) break;
char ch;
int m,k=0;
for (int i = 0; i < n - 1; i++)
{
cin >> ch >> m; //获取字符(顶点)
for (int j = 0; j < m; j++)
{
cin >> ch >> edge[k].w; //获取权重
edge[k].x = i;
edge[k].y = ch - 'A';
k++;
}
}
sort(edge,edge+k,cmp);
for(int i=0;i<MAXN;i++)
make_set(i);
sum=0;
for(int i=0;i<k;i++)
union_set(edge[i].x,edge[i].y,edge[i].w);
cout<<sum<<endl;
}
}
最小生成树例题:Jungle Roads ,Agri-Net ,Arctic Network ,Higeways