思路:题目的大致意思是任意两个QS要互通,每两个QS互通的条件是一条光缆和两个适配器。第一想到的是最小生成树的题,但是有一点不一样,就是题目不仅给了你边权,还给了你点权。转换一下思维就好了,把任意两个QS的边权看成光缆的耗费和两个QS的适配器的耗费即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f
int edge[1009][1009];
int dis[1009];
bool vis[1009];
int adp[1009]; //适配器的耗费
int n;
int prime()
{
memset(vis,false,sizeof(vis));
int i,j;
for(i=1; i<=n; i++)
{
dis[i]=edge[1][i];
}
vis[1]=true;
int minc;
int p;
int ans=0;
for(i=2; i<=n; i++)
{
minc=inf;
for(j=1; j<=n; j++)
if(!vis[j]&&minc>dis[j])
minc=dis[p=j];
ans+=minc;
vis[p]=true;
for(j=1; j<=n; j++)
{
if(!vis[j]&&dis[j]>edge[p][j])
{
dis[j]=edge[p][j];
}
}
}
return ans;
}
int main()
{
int t;
int i,j;
int m;
int x,y,w;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
edge[i][j]=inf;
for(i=1; i<=n; i++)
{
scanf("%d",&x);
adp[i]=x;
}
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
scanf("%d",&x);
edge[i][j]=edge[j][i]=x+adp[i]+adp[j]; //我的思路看懂了就懂了
}
int ans=prime();
printf("%d\n",ans);
}
return 0;
}