最小生成树,唯一不同的是点上有权值,如果边两端的点上也有费用需要计算
把点权全加到边权上去prim跑过去就好
#include <bits/stdc++.h>
using namespace std;
const int N=1200;
typedef int Real;
bool vis[N];
int n;
Real dis[N],e[N][N];
const int inf=100000000;
Real prim()
{
int i,j,u,v;
Real w,ans=0;
for(i=1; i<=n; i++) dis[i]=e[1][i];
memset(vis,0,sizeof(vis));
vis[1]=1;
for(i=2; i<=n; i++)
{
w=inf;
u=-1;
for(j=1; j<=n; j++) if(!vis[j]&&w>dis[j]) w=dis[j],u=j;
if(u==-1) return -1;
vis[u]=1;
ans+=w;
for(v=1; v<=n; v++) if(!vis[v])
if(dis[v]>e[u][v]) dis[v]=e[u][v];
}
return ans;
}
void Gao()
{
cin>>n;
int value[1200];
for (int i=1;i<=n;i++)
scanf("%d",value+i);
memset(e,1100000,sizeof(e));
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&e[i][j]),e[i][j]+=value[i]+value[j];
cout<<prim()<<endl;
}
int main()
{
int T;
cin>>T;
while (T--)
Gao();
return 0;
}