最小生成树 HDU 1233 还是畅通工程
学会了并查集,kruskal算法就没有大问题了
先对边的权值排序, 再不断添加边(要保证不形成回路,用并查集),直到添加的边数为n-1时停止
这题WA几次,检查几次算法发现无问题,最后发现数组开少了,囧~
#include<iostream>
#include <algorithm>
#define MAX 105
using namespace std;
struct Edge
{
int v;
int w;
int lenth;
};
int parent[MAX];
int find(int );
void Union(int , int);
bool cmp( Edge a, Edge b);
int main()
{
int n, num, count,m;
Edge edge[50*99+5];
int root_a, root_b;
int total_len;
while (cin >> n && n)
{
count = 1;
total_len = 0;
num = n*(n-1)/2;
m = 0;
memset(parent, -1, sizeof(int)*MAX);
for (int i = 0; i < num; i++)
scanf("%d%d%d", &edge[i].v, &edge[i].w, &edge[i].lenth);
sort(edge, edge+num, cmp);
//kruskal算法
while (count < n)
{
root_a = find(edge[m].v-1);
root_b = find(edge[m].w-1);
if (root_a != root_b)
{
Union(root_a, root_b);
total_len += edge[m].lenth;
count++;
}
m++;
}
cout << total_len << endl;
}
return 0;
}
bool cmp(Edge a, Edge b)
{
return a.lenth < b.lenth;
}
int find(int i)
{
int root, trail, lead;
for (root = i; parent[root] >= 0; root = parent[root]);
for (trail = i; trail != root; trail = lead)
{
lead = parent[trail];
parent[trail] = root;
}
return root;
}
void Union(int i , int j)
{
int temp = parent[i] + parent[j];
if (parent[i] > parent[j])
{
parent[i] = j;
parent[j] = temp;
}
else
{
parent[j] = i;
parent[i] = temp;
}
}
浙公网安备 33010602011771号