题目大意:
农民约翰准备在镇上建立起互联网,并连接到所有的农场。他已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。
思路:
这是一道最小生成树的题目。为大家带来O(n^3)和O(n^2)的方法。
代码:
O(n^3):
#include <cstdio>
using namespace std;
int a[101][101],n,b[101],k,sum,minn;
int main()
{
scanf("%d",&n);
b[1]=1; //第一个点已经在集合里面
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for (int q=1;q<=n-1;q++)
{
minn=2147483647;
for (int i=1;i<=n;i++)
if (b[i]==1) //如果i在集合里面
for (int j=1;j<=n;j++)
if (b[j]==0&&a[i][j]<minn&&i!=j) //j不再集合里面且这两个不是同一个点
{
k=j; //标记
minn=a[i][j];
}
if (minn!=2147483647)
{
sum+=minn; //计数
b[k]=1; //进入集合
}
}
printf("%d\n",sum);
return 0;
}
O(n^2):
#include <cstdio>
using namespace std;
int a[5001][5001],n,b[5001],k,sum,minn,c[5001];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
b[i]=i;
}
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 (c[i]<minn&&c[i]!=0) //求距离集合最近的一个在集合外的点
{
minn=c[i];
k=i; //记录
}
}
c[k]=0;
b[k]=1; //进入集合
sum+=minn;
for (int i=1;i<=n;i++)
if (b[i]!=1&&c[i]>a[k][i]) c[i]=a[k][i]; //重新判断集合到每个点的最近距离
}
printf("%d\n",sum);
return 0;
}
P.S:1682可以用以上任意一种方法做,1764只能用第二种方法做。
(此题跟最优布线问题极其相似)