题意:
一些公司想要相互联通来方便传递数据,公司与公司之间相互联接的话需要两个适配器和一条电缆,每个公司喜欢的不同型号的适配器。有t组数据,给你N个公司,下面一行是每个公司喜欢的适配器的价格,在下面是一个矩阵,是每个公司之间电缆的价格,问你全部联通最小需要多少钱。
题解:
每个公司都要联接可以知道用最小生成树,我用的是Kruskal,我这里WA了一发,是因为我是用边的代价去做的,选择出最小的边之后,再加上各自公司的编号对应的适配器的价格,后来发现,如果是下面这组数据的话就会出现错误:
1
3
10 20 100
0 10 1
10 0 1
1 1 0
如果用上面的思路去做的话会发现得到232,这是错误的,正确的答案是151。
那么要怎么改呢?我们可以在加入边的时候,直接放各自对应的适配器的价格进去边那里进行排序就可以得到答案了。
//Kruskal
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=1005;
struct node
{
int u,v,l;
}map[MAXN*MAXN];
int fa[MAXN];
int a[MAXN];
int n,k;
int find(int p)
{
return p==fa[p]? p:fa[p]=find(fa[p]);
}
bool cmp(node c,node d)
{
return c.l<d.l;
}
void Kruskal()
{
int sum=0;
for(int i=0;i<k;i++)
{
int P=find(map[i].u);
int Q=find(map[i].v);
if(P!=Q)
{
sum+=map[i].l;
fa[P]=Q;
}
}
printf("%d\n",sum);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
k=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
fa[i]=i;
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++)
{
int w;
scanf("%d",&w);
if(i==j)
continue;
map[k].u=i;
map[k].v=j;
map[k].l=w+a[i]+a[j];
k++;
}
sort(map,map+k,cmp);
Kruskal();
}
}