您的位置:首页 > 编程语言 > C语言/C++

新的开始( [USACO08OCT]打井Watering Hole)

2017-09-26 11:49 211 查看
新的开始

(newstart.pas/c/cpp)

【 题目描述】

话说小 FF 在经历了上次“寻找古代王族遗产” 的探险后, 成为了世界上最伟大的探险

家并拥有了一大笔财富。 当然他不能坐吃山空, 必须创造财富!! 于是他买下了传说中的

GreedIsland 并优先发展那里的采矿业„„他还将其称为 GreedIsland 的“ NewBe_One” 计划。

发展采矿业当然首先得有矿井, 小 FF 花了上次探险获得的千分之一的财富请人在岛上

挖了 N 口矿井, 但他似乎忘记考虑的矿井供电问题„„

为了保证电力的供应, 小 FF 想到了两种办法:

1、 在这一口矿井上建立一个发电站, 费用为 v( 发电站的输出功率可以供给任意多个

矿井)。

2、 将第 i 口矿井与已经有电力供应的第 j 口矿井之间建立电网的费用为 p[i,j]。

小 FF 希望身为”NewBe_One”计划首席工程师的你帮他想出一个保证所有矿井电力供应的最

小花费。

【 输入格式】

第一行一个整数 N,表示矿井总数。

第 2~N+1 行, 每行一个整数, 第 i 个数 v[i]表示在第 i 口矿井上建立发电站的费用。 接

下来为一个 N×N 的矩阵 P, 其中 p[i,j]表示在第 i 口矿井和第 j 口矿井之间建立电网的费用

( 数据保证有 p[i,j]=p[j,i],且 p[i,i]=0)。

【 输出格式】

输出共一行一个整数, 表示让所有矿井获得充足电能的最小花费。

【 输入样例】

4 5 4 4 3 0

2 2 2

2 0 3 3

2 3 0 4

2 3 4 0

【 输出样例】

9

【 输出样例说明】

小 FF 可以选择在 4 号矿井建立发电站然后把所有矿井都与其建立电网, 总花费是

3+2+2+2=9。

【 数据规模】

对于 30%的数据: 1≤N≤50;

对于 100%的数据: 1≤N≤300; 1≤v[i],p[i,j]≤10^5;

这题看着没有任何头绪,但其实只是最小生成树。

这题看着没有任何头绪,但其实只是最小生成树。

这题看着没有任何头绪,但其实只是最小生成树。

先看张图!



我们可以这么想,岛上有一座另外的发电站p。

在x这个矿井造一个发电站,消耗w[i],就相当于x点到p点的消耗经费为w[i]

于是就可以构筑出上面那张图,上图求所有点相连的最小值不就是最小生成树吗?

code:

#include<bits/stdc++.h>
using namespace std;
int i,j,k,n,m,tot,ans,fa[305],w[305],f[305][305],top,re;
int read(){
char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
int x=0,y=1;if(c=='-') y*=-1;else x=c-'0';
while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';
return x*y;
}
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void unionn(int x,int y){
x=find(x);y=find(y);
if(x>y) fa[x]=y;
else fa[y]=x;
}
struct node{
int a,b,len;
}a[100005];
int cmp(node a,node b){
if(a.len<b.len) return 1;
else return 0;
}
int main()
{
n=read();re=0;
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
f[i][j]=f[j][i]=read();
if(j>=i+1) a[++top].a=i,a[top].b=j,a[top].len=f[i][j];
}
for(int i=1;i<=n+1;i++) fa[i]=i;
for(int i=1;i<=n;i++) a[++top].a=i,a[top].b=n+1,a[top].len=w[i];
sort(a+1,a+1+top,cmp);
for(int i=1;i<=top;i++){
if(find(a[i].a)!=find(a[i].b)){
k++;unionn(a[i].a,a[i].b);
ans+=a[i].len;
}
if(k==n) break;
}
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 最小生成树c++