看题传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1863
这题是最小生成树的裸题,具体的算法内容挺简单的,记录一下实现过程中踩的坑……
首先这题用优先队列应该是最简单的,直接在结构体里重载运算符,我tm只记得用队列方便,却忘了优先队列更方便……像这种判断连通分量的,循环看看谁的父亲是自己就行了。
再一个就是kruskal算法里merge函数最后要有返回值以判断连接是否成功。
自己实现的时候千难万难,回过头来再看又觉得没什么。
上一波实现吧
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 11000;
int fa[MAXN];
struct Edge{
int u, v;
int w;
}Graph[MAXN];
int getFa(int a){
return fa[a] == a? a : fa[a] = getFa(fa[a]);
}
int Merge(int a, int b){
int faA = getFa(a), faB = getFa(b);
if(faA != faB){
fa[faA] = faB;
return 1;
}
else
return 0;
}
bool cmp(Edge a, Edge b){
if(a.w != b.w)
return (a.w < b.w);
}
int main()
{
//freopen("input.txt", "r", stdin);
int n, m;
while(~scanf("%d %d", &n, &m) && n){
for(int i = 0;i < n;++i){
scanf("%d %d %d", &Graph[i].u, &Graph[i].v, &Graph[i].w);
}
if(n < m-1){
printf("?\n");
continue;
}
for(int i = 1;i <= m;++i)
fa[i] = i;
sort(Graph, Graph + n, cmp);
queue<Edge> qu;
for(int i = 0;i < n;++i){
qu.push(Graph[i]);
}
int ans = 0;
bool flag = true;
for(int i = 0;i < n;i++){
if(Merge(qu.front().u, qu.front().v) ){
ans += qu.front().w;
}
qu.pop();
}
int cnt = 0;
for(int i = 1;i <= m;++i){
if(fa[i] == i){
cnt++;
}
}
if(cnt == 1)
printf("%d\n",ans);
else
printf("?\n");
}
return 0;
}