首先因为这题是连通性问题求最值,考虑最小生成树是否可做,这题一个比较不同的地方是它每一个点有权值,我们考虑能否将点的权值转化成边权,因为如果能够转化成功,我们就可以很轻松的用最小生成树求解,我们可以建立一个新的虚拟节点,并将所有的点与这个点连一条边权为那些点点权的边,然后在新图中求最小生成树即可
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
struct edge
{
int fr,to,cost;
}e[maxn];
int n,tot,cnt,father[maxn],ans;
bool cmp(edge a,edge b)
{
return a.cost<b.cost;
}
int getfather(int x)
{
if (x!=father[x]) x=getfather(father[x]);
return father[x];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
e[++tot].fr=0;
e[tot].to=i;
scanf("%d",&e[tot].cost);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
int a;
scanf("%d",&a);
if (a==0) continue;
e[++tot].fr=i;
e[tot].to=j;
e[tot].cost=a;
}
sort(e+1,e+tot+1,cmp);
for (int i=1;i<=n;i++) father[i]=i;
for (int i=1;i<=tot;i++)
{
int x=e[i].fr;
int y=e[i].to;
x=getfather(x);
y=getfather(y);
if (x==y) continue;
father[x]=y;
ans+=e[i].cost;
cnt++;
if (cnt==n) break;
}
printf("%d\n",ans);
return 0;
}