新的开始
题目描述
发展采矿业当然首先得有矿井,小 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=2e5;
int cnt;
struct node{
int u,v,w;
}a[N];
int f[N];
int n;
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
bool cmp(node a,node b){
return a.w<b.w;
}
int kru(){
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++)f[i]=i;
int sum=0;
for(int i=1;i<=cnt;i++){
int u=a[i].u;
int v=a[i].v;
int w=a[i].w;
if(find(u)==find(v))continue;
else{
f[find(u)]=find(v);
sum+=w;
}
}
return sum;
}
signed main(){
scanf("%d",&n);
int mn=INT_MAX;
int x;
for(int i=1;i<=n;i++){
scanf("%d",&x);
mn=min(mn,x);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
a[++cnt]=node{i,j,x};
}
}
printf("%d",kru()+mn);
}
注意,这上面的代码是错的!!!!!!!
这里只需要做一个小改动,就是把每个发电站也建立到生成树里面去,这样就可以实现找最小费用了
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
int cnt;
struct node{
int u,v,w;
}a[N];
int f[N];
int n;
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
bool cmp(node a,node b){
return a.w<b.w;
}
int kru(){
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++)f[i]=i;
int sum=0;
for(int i=1;i<=cnt;i++){
int u=a[i].u;
int v=a[i].v;
int w=a[i].w;
if(find(u)==find(v))continue;
else{
f[find(u)]=find(v);
sum+=w;
}
}
return sum;
}
signed main(){
scanf("%lld",&n);
int x;
for(int i=1;i<=n;i++){
scanf("%lld",&x);
a[++cnt]={0,i,x};
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%lld",&x);
a[++cnt]=node{i,j,x};
}
}
printf("%lld",kru());
}
浙公网安备 33010602011771号