题目 2397:
信息学奥赛一本通T1488-新的开始
时间限制: 2s 内存限制: 192MB 提交: 33 解决: 20
题目描述
发展采矿业当然首先得有矿井,小 F 花了上次探险获得的千分之一的财富请人在岛上挖了 n 口矿井,但他似乎忘记考虑的矿井供电问题……
为了保证电力的供应,小 F 想到了两种办法:
在这一口矿井上建立一个发电站,费用为 v(发电站的输出功率可以供给任意多个矿井)。
将这口矿井与另外的已经有电力供应的矿井之间建立电网,费用为 p。
小 F 希望身为「NewBe_One」计划首席工程师的你帮他想出一个保证所有矿井电力供应的最小花费。
输入格式
第一行一个整数 n,表示矿井总数。
第 2∼n+1行,每行一个整数,第 i 个数 vi 表示在第 i 口矿井上建立发电站的费用。
接下来为一个 n×n 的矩阵 p,其中 pi,j 表示在第 i 口矿井和第 j 口矿井之间建立电网的费用(数据保证有pi,j=pj,i ,且 pi,i=0。
输出格式
输出仅一个整数,表示让所有矿井获得充足电能的最小花费。
样例输入
复制
4 5 4 4 3 0 2 2 2 2 0 3 3 2 3 0 4 2 3 4 0样例输出
复制
9
思路:
一道经典题,看到超级源点应该就都反应过来了。
和城市建设那道题类似,不过这题更简单一点。
一般建码头,发电站这样的·,建立孤立点又可以影响其他点的题可以考虑超级源点。
#include<bits/stdc++.h> using namespace std; const int N = 310, M = 100100; int p[N]; struct edge {int a, b, w;bool operator<(edge& W) {return w < W.w;} }e[M]; int n; int ans; int find(int x) {if (x != p[x]) {p[x] = find(p[x]);}return p[x]; } int main() {cin >> n;for (int i = 1;i <= n;i++) {int v;cin >> v;e[i].a = i;e[i].b = 0;e[i].w = v;}int cnt = n;for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {int v;cin >> v;if (j == i) {continue;}cnt++;e[cnt].a = i;e[cnt].b = j;e[cnt].w = v;}}sort(e + 1, e + cnt);for (int i = 1;i <= n;i++) {p[i] = i;}for (int i = 1;i <= cnt;i++) {int a = e[i].a;int b = e[i].b;int x = find(a);int y = find(b);if (x != y) {p[x] = y;ans += e[i].w;}}cout << ans; }