POJ 1251 最小生成树——kruskal与prim
最小生成树裸题,复习用。
代码
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
const int maxn = 100;
struct Edge{
int u,v,w;
bool operator < (const Edge &e) const{
return w > e.w;
}
};
priority_queue<Edge> pq;
int F[maxn];
int find(int x){
return F[x] == -1 ? x : find(F[x]);
}
// kruskal算法,寻找图的最小生成树大小,-1代表不连通
int kruskal(int n){
memset(F, -1, sizeof(F));
int ans = 0, cnt = 0;
while (!pq.empty()) {
// 假如该边不在同一个连通分量内
if(find(pq.top().u) != find(pq.top().v)){
// 选取该边,并将该边的两端加入连通分量中
F[find(pq.top().u)] = find(pq.top().v);
ans += pq.top().w;
cnt++;
}
pq.pop();
if(cnt == n-1) break;
}
// 将队列清空
while (!pq.empty()) {
pq.pop();
}
return cnt == n-1 ? ans : -1;
}
int vis[maxn];// 记录某个点是否在最小生成树集合中
int lowc[maxn];// 各个点到最小生成树集合的最短距离
int m[maxn][maxn];
const int INF = 0x3f3f3f3f;
// prim算法求图的最小生成树,-1代表不连通
int prim(int n){
int ans = 0;
memset(vis, 0, sizeof(vis));
vis[0] = 1;
// 初始化lowc
for(int i = 0;i < n;i++){
lowc[i] = m[0][i];
}
// 重复n-1次
for(int i = 1;i < n;i++){
// 找到当前距离最近的最小生成树集合以外的点
int minc = INF;
int p = -1;
for(int j = 0;j < n;j++){
if(!vis[j] && lowc[j] < minc){
minc = lowc[j];
p = j;
}
}
// 假如找不到,返回-1
if(p == -1){
return -1;
}
// 更新答案
ans += lowc[p];
vis[p] = 1;
// 松弛
for(int j = 0;j < n;j++){
if(!vis[j] && lowc[j] > m[p][j]){
lowc[j] = m[p][j];
}
}
}
return ans;
}
int main(){
while(true){
int n;
cin>>n;
if(n == 0) break;
memset(m, 0x3f, sizeof(m));
for(int j = 1;j < n;j++){
char village;
int k;
cin>>village>>k;
for(int i = 0;i < k;i++){
char dest;
int weight;
cin>>dest>>weight;
// Edge tmp;
// tmp.u = village - 'A';
// tmp.v = dest - 'A';
// tmp.w = weight;
// pq.push(tmp);
m[village-'A'][dest-'A'] = weight;
m[dest-'A'][village-'A'] = weight;
}
}
cout<<prim(n)<<endl;
}
}
184KB/252KB 0MS