题目大意:
某个局域网内有n(n<=100)台计算机,每台计算机都会有网线连接,而且计算机之间有些没必要连接的网线,因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用f(i,j)表示i,j之间连接的畅通程度(f(i,j)<=1000),f(i,j)值越小表示i,j之间连接越通畅,f(i,j)为0表示i,j之间无网线连接。请问在所有电脑都连接的情况下,如何减少网线,使网线连接最畅通?
思路:
其实这道题就是一个最小生成树。其实它所谓的“畅通程度”就可以看成连接两台电脑的代价,我们要找出一种方法让这种代价最小。求出代价的最小值后,用最开始连接的代价减去最小值即可。
比如:
我们求出来的最低代价为5+2+1+3=11
一开始的代价为8+5+2+1+3=19
则我们最多减少19-11=8的代价。
代码:
#include <cstdio>
using namespace std;
int a[101][101],n,m,b[101],c[101],x,y,k,minn,sum,ans;
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&k);
a[x][y]=a[y][x]=k;
ans+=k; //总代价
}
b[1]=1; //进入集合
for (int i=1;i<=n;i++)
if (a[1][i]!=0) c[i]=a[1][i]; //计算各个集合外的点到集合最近距离
for (int q=1;q<=n-1;q++)
{
minn=2147483647;
for (int i=1;i<=n;i++)
if (b[i]!=1&&c[i]!=0&&c[i]<minn) //如果有集合外的点离集合更近
{
minn=c[i];
k=i;
}
sum+=c[k];
c[k]=0;
b[k]=1; //进入集合
for (int i=1;i<=n;i++) //重新计算各个集合外的点到集合最近距离
if (b[i]==0&&a[i][k]!=0&&(c[i]==0||c[i]>a[i][k]))
c[i]=a[i][k];
}
printf("%d\n",ans-sum); //最多可以减少的代价
return 0;
}