这道题也是用最小生成树当中的Prim算法。
不过,这道题有个地方要注意,两个顶点之间的边的权还要加上两个顶点对应的adapter的费用,否则会出错。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 100000000
using namespace std;
const int maxn=1e3+5;
int map[maxn][maxn],dis[maxn],a[maxn]; //map构造矩阵,a记录每个顶点对应adapter的费用
bool vis[maxn];
int Prim(int n)
{
int ans=0;
for(int i=1;i<=n;i++)
{
vis[i]=0;
dis[i]=map[1][i];
}
vis[1]=1;
for(int i=1;i<=n;i++)
{
int temp=inf,k;
for(int j=1;j<=n;j++)
if(!vis[j]&&temp>dis[j])
{
temp=dis[j];
k=j;
}
if(temp==inf)
break;
ans=ans+dis[k];
vis[k]=1;
for(int j=1;j<=n;j++)
if(!vis[j]&&dis[j]>map[k][j])
dis[j]=map[k][j];
}
return ans;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
if(i!=j) map[i][j]=map[i][j]+a[i]+a[j]; //在i和j之间建立链接的费用,加上两个顶点对应adapter的费用,才是真正的i和j连通的费用
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cout<<map[i][j]<<' ';cout<<endl;
}*/
printf("%d\n",Prim(n));
}
return 0;
}