概括
简单来说,最小生成树就是在连通的赋权图中找出具有最小权的生成树。
- 树不可以形成回路
- 生成树种的每一个结点和线段都是从图中取出的
- 最小生成树对应的权值最小
Kruskal算法
从赋权图中找出权重小的边,放进右图中的树中,检查不能出现回路
#include<bits/stdc++.h>
using namespace std;
#define N 100
//图的结构体
struct edge{
int u,v,value;
}myedge[N*N];
int n,m,p[N];
//从小到大排序函数
bool cmp(const edge& p1,const edge& p2){
return p1.value<p2.value;
}
//并查集
int find(int x){
return (p[x]==x)?x:(p[x]=find(p[x]));
}
int main(){
while(scanf("%d %d",&n,&m)==2){
char a[2],b[2];
int i,x,y,sum=0,value,cnt=0;
for(i=0;i<m;i++){
cin>>a>>b>>myedge[i].value;
myedge[i].u=a[0]-'a';
myedge[i].v=b[0]='a';
}
for(i=0;i<n;i++) p[i]=i;
sort(myedge,myedge+m,cmp);
for(i=0;i<m;i++){
value=myedge[i].value;
x=find(myedge[i].u);
y=find(myedge[i].v);
if(x!=y){
sum+=value;
//p[y]=x;
cnt++;
if(cnt>=n-1) break;
}
}
cout<<sum<<"\n";
}
return 0;
}
Prim算法
从一个结点出发,向外延伸线段,选取权重最小的临界点,逐步生成最小生成树
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100;
bool vis[maxn];
int dis[maxn],g[maxn][maxn];
int n,m,ans;
int main(){
while(scanf("%d %d",&n,&m)==2){
char a[2],b[2];
memset(g,0x7f,sizeof(g));
memset(vis,false,sizeof(vis));
for(int i=0;i<m;i++){
cin>>a>>b>>ans;
g[a[0]-'a'][b[0]-'a']=g[b[0]-'a'][a[0]-'a']=ans;
}
for(int i=0;i<n;i++){ //遍历起点
dis[i]=g[0][i];//记录结点距离
ans=0;
vis[0]=true;
dis[n]=0x7fffffff;//初始化为“断路”
for(int i=0;i<n-1;i++){
int k=n;
for(int j=0;j<n;j++){ //遍历邻接点
if(vis[j]) continue;
if(dis[j]<dis[k]) k=j;
}
ans += dis[k];
vis[k]=true;
for(int j=0;j<n;j++){
if(g[k][j]<dis[j]){
dis[j]=g[k][j];
}
}
}
cout<<ans<<"\n";
}
}
return 0;
}