洛谷1550
构图很巧妙,建立一个超级源点,所有连向自己的边(即打井)改为连向这个超级源点,最后跑一个最小生成树即可。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
struct node{
int from,to,w;
friend inline bool operator<(const node &a,const node &b){
return a.w<b.w;
}
}edge[MAXN];
int n,ans,num,tot,a;
int fa[400],val[MAXN];
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
int Read()
{
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int main()
{
n=Read();
for(int i=1;i<=n;i++)
val[i]=Read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int x=Read();
if(i!=j)
{
edge[++tot].w=x;
edge[tot].from=i;
edge[tot].to=j;
}
else
{
edge[++tot].w=val[i];
edge[tot].from=0;
edge[tot].to=i;
}
}
for(int i=0;i<=n;i++)
fa[i]=i;
sort(edge+1,edge+tot+1);
for(int i=1;i<=tot;i++)
{
int x=find(edge[i].from);
int y=find(edge[i].to);
if(x!=y)
{
ans+=edge[i].w;
fa[x]=y;
num++;
}
if(num==n)
break;
}
printf("%d",ans);
return 0;
}