杭电 hdu 1102 Constructing Roads (最小生成树)
题意:有n个村庄,要将所有的村庄连接起来,而这些村庄原先就有一些村庄是相互通的,然后告诉你所有的村庄相互之间的距离,问你还要
修多少长的距离能让所有村庄连接起来
首先输入n,表示有多少个村庄,
然后是n*n的矩阵,表示每个村庄之间的距离
然后是m,表示本来存在多少的路
然后a,b表示a村庄到b村庄连通
题解:通过最小生成树,先将已经连通的村庄连接起来,然后再从矩阵中找边,找短的,并且合适的边,组成完整的最小生成树
其实就是通过并查集,查找祖先结点不同的,就连接起来。
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 10005;
struct node{ //用来存放边,从from到to,还有相隔的距离
int a;
int b;
int v;
}tree[maxn];
bool cmp(node a, node b){ //优先级,使结构体中距离短的放在前面
return (a.v < b.v);
}
int father[maxn];
int sum;
void Init (){
int i;
for (i = 1; i < maxn; ++i) //让刚开始的父亲结点设为自己
father[i] = i;
}
int Find (int x){ //寻找祖先结点
int rt = x;
if (father[x] != x){
rt = Find (father[x]);
father[x] = rt;
}
return rt;
}
bool Union(int a, int b){
int fa = Find (a);
int fb = Find (b);
if (fa != fb){ //如果祖先结点不同,那边表明没有环,可以连接
father[fa] = fb;
return true;
}
return false;
}
int main (){
int T, n, a, b, i, j;
while (scanf ("%d", &T) != EOF){
int num = 0;
sum = 0;
Init ();
for (i = 1; i <= T; ++i)
for (j = 1; j <= T; ++j){
scanf ("%d", &tree[num].v); //将边存储到tree[]结构体中
tree[num].a = i;
tree[num++].b = j;
}
sort (tree, tree + (T * T), cmp); //优先级排序
scanf ("%d", &n);
for (i = 1; i <= n; ++i){ //构造树
scanf ("%d%d", &a, &b);
Union(a, b);
}
for (i = 0; i < T * T; ++i){
if (Union (tree[i].a, tree[i].b)){
sum += tree[i].v; //记录总共要修的距离
}
}
printf ("%d\n", sum);
}
}