题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1233
题解:
利用贪心思想,先将每一条路的权值排序,优先连接权值短的路。
然后在处理路的连接问题上用并查集可以轻松实现。
主要步骤:枚举每一条可以连接的路然后再判断其祖宗节点是否相同,如果不同则进行两路的连线,并累计权值和直至所有的路的祖宗节点都相等,则累计成功。
另外注意:数据范围问题,MAXN最小应开到4950
AC代码:
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 50 * 99 +5;
int pre[MAXN];
struct Infor{
int x;
int y;
int length;
}s[MAXN];
bool cmp(Infor s1, Infor s2) {
return s1.length < s2.length;
}
int Find(int x) {
int r = x;
while (pre[r] != r)
r = pre[r];
int i = x, j;
while (i != r) {
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
void Join(int x, int y) {
x = Find(x);
y = Find(y);
if(x != y)
pre[x] = y;
}
int main() {
int n;
while (cin >> n && n) {
int m = n * (n - 1) / 2;
for(int i = 1; i <= n; i++) {
pre[i] = i;//初始化节点
}
for(int i = 0; i < m; i++) {
cin >> s[i].x >> s[i].y >> s[i].length;
}
int sum = 0;
sort(s, s + m, cmp);
for(int i = 0; i < m; i++) {
if(Find(s[i].x) != Find(s[i].y)) {//还未连接,加入进去
Join(s[i].x, s[i].y);
sum += s[i].length;
}
}
cout << sum << endl;
}
return 0;
}