从每个点到源点连边表示建水库的花费。每个点之间相互连边,跑MST即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 350
#define maxe 150050
using namespace std;
struct edge
{
int u,v,w;
}e[maxe];
int n,x,nume=0,father[maxv],ans=0;
bool cmp(edge x,edge y)
{
return x.w<y.w;
}
void addedge(int u,int v,int w)
{
e[++nume].v=v;
e[nume].u=u;
e[nume].w=w;
}
int getfather(int x)
{
if (x!=father[x])
father[x]=getfather(father[x]);
return father[x];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
addedge(0,i,x);
father[i]=i;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
scanf("%d",&x);
if (i!=j) addedge(i,j,x);
}
sort(e+1,e+nume+1,cmp);
for (int i=1;i<=nume;i++)
{
int u=e[i].u,v=e[i].v,w=e[i].w;
int f1=getfather(u),f2=getfather(v);
if (f1!=f2)
{
father[f1]=f2;
ans=ans+w;
}
}
printf("%d\n",ans);
return 0;
}