题目链接在这里
题目大意
有N个村庄,每个村庄之间都有一定的距离,想建几条路使得村庄之间相互连通,问所需要花费的最小代价是什么。(有的村庄之间是相互连通的)
解题思路
相互连通的村庄之间的距离置为0,然后将所有村庄之间的距离放到堆里,直接最小生成树莽出来就完事了。
代码如下
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define clr(x) memset(x, 0, sizeof(x))
#define rep(i, x) for(int i = 0; i < x; ++i)
using namespace std;
const int MaxN = 110;
struct Edge{
int x, y, val;
bool operator < (const Edge& x) const{
return val > x.val;
}
};
int n, q;
int map[MaxN][MaxN];
int r[MaxN], par[MaxN];
int Find(int x){
if(x == par[x]) return x;
return par[x] = Find(par[x]);
}
void unite(int x, int y){
x = Find(x);
y = Find(y);
if(x == y) return;
if(r[x] < r[y]) par[x] = y;
else{
par[y] = x;
if(r[x] == r[y]) ++r[x];
}
}
bool check(int x, int y){
return Find(x) == Find(y);
}
int main(){
ios::sync_with_stdio(false);
cin >> n;
clr(r);
rep(i, MaxN) par[i] = i;
rep(i, n){
rep(j, n){
cin >> map[i][j];
}
}
cin >> q;
int x, y;
rep(i, q){
cin >> x >> y;
map[x - 1][y - 1] = map[y - 1][x - 1] = 0;
}
priority_queue<Edge> que;
rep(i, n){
rep(j, i){
que.push(Edge{i, j, map[i][j]});
}
}
int ans = 0;
while(--n){
Edge e = que.top();
que.pop();
if(check(e.x, e.y)){
++n;
continue;
}
ans += e.val;
unite(e.x, e.y);
}
cout << ans << endl;
return 0;
}