详情: | 有一个城市准备开发一片荒地,目前已经规划好了一些居民点,还要建些道路。由于经费问题,他们想在任意两点间的距离最短的前提下,用尽可能少的投资把各个点连接起来。需要注意的是并不是任意两个居民点间都能直接相连给出两两居民点间建路的花费(与长度成正比),你可以帮他们选择一个最佳方案吗? |
输入格式: | |
输出格式: | |
样例: |
|
补充:
第一行是个N<=100,表示N个居民点。
下面是个N*N的矩阵,第i行第j列,表示i到j的花费,可能有负数,表示两地不相连。保证有解。
我刚开始没有怎么看明白,好吧,现在也不是很明白。使用一个flag数值来标记,利用Floyd来做。关于结果1:输出总费用,如果有边进行了松弛,则不用进行加入,因为可以通过其他路径来使这两点到达。需要将所有的居民点连接,则利用循环,具体看代码。关于结果2:输出有无道路,0和1的选择。计入总费用的路,直接重新让权值改变,1->2 ,同时让 2->1 具体看代码。
代码如下:
#include <stdio.h>
int n,e[101][101],flag[101][101];
int main()
{
scanf("%d",&n);
int i,j,inf = 9999999;
for(i = 0;i < n;i++)//初始化
{
for(j = 0;j < n;j++)
{
scanf("%d",&e[i][j]);
if(e[i][j]<0)
e[i][j] = inf;//表示不可到达
flag[i][j] = 1;
}
}
for(k = 0;k < n;k++)//通过k这条边来进行松弛
for(i = 0;i < n;i++)
{
if(i==k)
continue;
for(j = 0;j < n;j++)
{
if(j==k)
continue;
if(e[i][j]>=e[i][k]+e[k][j])
{
flag[i][j] = 0;//表示这条道路不需要修
e[i][j] = e[i][k]+e[k][j];//更新最小值
}
}
int sum = 0;
for(i = 0;i < n;i++)
{
for(j = i+1;j < n;j++)
{
if(flag[i][j])//表示这条道路可修
{
sum += e[i][j];
e[i][j] = 1;//这条道路可修
e[j][i] = 1;
}
}
}
printf("%d\n",sum);
for(i = 0;i < n;i++)
{
for(j = 0;j < n;j++)
{
if(e[i][j]==1)
printf("1 ");
else
printf("0 ");
}
printf("\n");
}
}
return 0;
}