今天刚学了最小生成树的算法,发现prim的算法和dijkstra算法几乎差不多,就是更新的时候是更新边权,不是起点到当前点的值,还有一个按边权排序再遍历加建树的kruskal算法。
先贴prim算法的模板:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int edge[30][30],vis[30],cost[30],n;
void prim() {
cost[1] = 0;
int ans = 0;
while(true) {
int v = -1;
for(int u = 1;u <= n;u++) { //先找出从点1到其权值最小的顶点
if(!vis[u] && (v == -1 || cost[u] < cost[v])) v = u;
}
if(v == -1) break;
vis[v] = 1;
ans += cost[v]; //加入结果中
for(int u = 1;u <= n;u++) //从点1到其他点的最小权值的更新
cost[u] = min(cost[u],edge[v][u]);
}
printf("%d\n",ans);
}
int main() {
while(scanf("%d",&n) != EOF && n) {
memset(edge,inf,sizeof(edge));
memset(cost,inf,sizeof(cost));
memset(vis,0,sizeof(vis));
for(int i = 1;i < n;i++) {
char a[2],b[2]; int t,x;
scanf("%s%d",&a,&t);
for(int i = 1;i <= t;i++) {
scanf("%s%d",&b,&x);
edge[a[0]-'A'+1][b[0]-'A'+1] = x;
edge[b[0]-'A'+1][a[0]-'A'+1] = x;
}
}
prim();
}
return 0;
}
再贴一个kruskal算法的模板:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
struct node{
int u,v,cost;
} edge[100005];
int u,e,fa[505];
int query(int x) { //利用并查集高效的合并树
return fa[x] == x ? x : fa[x] = query(fa[x]);
}
bool cmp(node a,node b) {
return a.cost < b.cost;
}
int kruskal() {
sort(edge,edge+e,cmp); //先按边权排序
for(int i = 1;i <= u;i++) fa[i] = i;
int ans = 0;
for(int i = 0;i < e;i++) { //按边权最小的建树合并
node temp = edge[i];
int a = query(temp.u);
int b = query(temp.v);
if(a != b) {
fa[b] = a;
ans += temp.cost;
}
}
return ans;
}
int main() {
while(scanf("%d",&u) != EOF && u != 0) {
scanf("%d",&e);
for(int i = 0;i < e;i++)
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost);
int ans = kruskal();
printf("%d\n",ans);
}
}