发展采矿业当然首先得有矿井,小 FF 花了上次探险获得的千分之一的财富请人在岛上挖了 n 口矿井,但他似乎忘记了考虑矿井供电问题。
为了保证电力的供应,小 FF 想到了两种办法:
在矿井 i 上建立一个发电站,费用为 vi(发电站的输出功率可以供给任意多个矿井)。 将这口矿井 i 与另外的已经有电力供应的矿井 j
之间建立电网,费用为 pi,j。 小 FF 希望你帮他想出一个保证所有矿井电力供应的最小花费方案。
输入格式: 第一行包含一个整数 n,表示矿井总数。
接下来 n 行,每行一个整数,第 i 个数 vi 表示在第 i 口矿井上建立发电站的费用。
接下来为一个 n×n 的矩阵 P,其中 pi,j 表示在第 i 口矿井和第 j 口矿井之间建立电网的费用。
数据保证 pi,j=pj,i,且 pi,i=0。
输出格式: 输出一个整数,表示让所有矿井获得充足电能的最小花费。
数据范围 1≤n≤300, 0≤vi,pi,j≤105
像这种 找总体代价最小的问题 考虑到MST,每个点又带权值,并且含有边权,想到超级源点。
我们假设存在一个超级发电站,并且设每个点与这个超级源点存在一条边,边权就是建设这个点的代价,那么我直接跑MST使得每个点通电的最小代价就行啦
这个题意思并不是只能建一个发电站,可以有很多个连通块,最后使得每个点都能发电即可
例如:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
struct node{
int from,to,d;
}s[N];
int cnt=0;
int cmp(const node s1,const node s2){
return s1.d<s2.d;
}
int father[N];
int find(int x){
if(x==father[x]) return x;
return father[x]=find(father[x]);
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) father[i]=i;
for(int i=1;i<=n;i++){
int v;cin>>v;
s[++cnt]={i,n+1,v};
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
cin>>x;
if(i>j) s[++cnt]={i,j,x};
}
}
sort(s+1,s+1+cnt,cmp);
int res=0;
for(int i=1;i<=cnt;i++){
int a=s[i].from,b=s[i].to,w=s[i].d;
int dx=find(a),dy=find(b);
if(dx!=dy){
father[dx]=dy;
res+=w;
}
}
cout<<res<<endl;
return 0;
}
水篇题解TAT