http://www.lydsy.com/JudgeOnline/problem.php?id=1601
题意:给你n个点,要求把每个点上都连上水,其中有两种方式
一种是将点和有水的点连起来
另一种是在这个点上建水库
两种方式在每个点上各自有不同的花费
求将所有店连通上水的最小费用
这道题其实是最小生成树
只不过饶了一点弯
其实我们完全将水库当成一个虚拟的点
每次建水库的费用其实就是将这个点向水库连上一个边
点之间的费用用点之间的边表示
然后最小生成树
解决问题
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct rec{
int x,y,z;
}edge[100000];
bool operator <(rec a,rec b){
return a.z<b.z;
}
int fa[1000],A[1000],B[1000][1000];
int get(int x){
if(x==fa[x]) return x;
return fa[x]=get(fa[x]);
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;++i){
cin>>A[i];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)
cin>>B[i][j];
}
int tot=0,ans=0;
for(int i=1;i<=n;++i){
edge[++tot].x=i;
edge[tot].y=n+1;
edge[tot].z=A[i];
}
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
edge[++tot].x=i;
edge[tot].y=j;
edge[tot].z=B[i][j];
}
}
sort(edge+1,edge+1+tot);
for(int i=1;i<=n+1;++i)
fa[i]=i;
for(int i=1;i<=tot;++i){
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y) continue;
fa[x]=y;
ans+=edge[i].z;
}
cout<<ans<<endl;
}