选地址(最短路径+floyd算法)

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
小X有很多朋友,分布在N个城市。
这N个城市之间,有些有直接的道路,有些是间接联通的(保证任何两个城市都可以相互到达。)。
但是,经过每条道路都是有代价的,于是,小X希望你来帮他找出一个城市,使得他的所有朋友到这个城市的代价最小。
输入
输入共2* N+1行,
其中第一行为一个整数N,
第2~N+1行
每行有N个整数、表示两个城市间的代价,(0表示不直接连通)
第n+2~2*N+1行
每行一个整数。表示每个城市中小X的朋友数。
输出
输出有两行。
第一行为你选中的城市
第二行为最小需要的代价。
样例输入 Copy

5
0 1 2 0 0
1 0 0 0 20
2 0 0 10 0
0 0 10 0 1
0 20 0 1 0
2
3
4
5
6

样例输出 Copy

4
109

提示
对于100%的数据,n<=200,输出保证不超过long long int

对于任意一个城市,其余所有城市的朋友只有经过最短路时才满足所有的朋友到该城市的代价最小,因此可以先求任意两点的最短路径,然后再求最小的代价。
题目数据量较小,采用floyd算法。floyd算法是求解最短路径的一种算法,采用动态规划的思想。我们可以这样想,从i点到j点,有两种方案,一是直接从i到j,另一种是从i经过第三个点k(若干个)到达j。由此floyd算法的思路就出来了。对于任意的i、j两点,遍历所有的点,寻找从i直接到j和从i经过第三个点到j的最小值,遍历结束后求得的最小值就是从i到j的最短路径。
floyd算法的核心代码就4行,直接套就完事了。

for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
         for(j=1;j<=n;j++)
            path[i][j]=min(path[i][j],path[i][k]+path[k][j]);
#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int path[205][205];//表示任意两点的距离
int fri[205];
int main()
{
    int n,i,j,k,dis,ans,city,t;
    scanf("%d",&n);
    for(i=1;i<=n;i++)     //(1)同一个点(i到i)之间的距离为0
    {                     //(2)0表示不直接连通,距离设为0x3f3f3f3f(可以表示无穷大)
        for(j=1;j<=n;j++) //(3)连通的不同的点的距离设为dis
        {
            scanf("%d",&dis);
            if(i==j)path[i][j]=0;
            else
            {
                if(dis==0)path[i][j]=inf;
                else path[i][j]=dis;
            }
        }
    }
    for(i=1;i<=n;i++)scanf("%d",&fri[i]);
    ans=inf;
    for(k=1;k<=n;k++)//floyd算法核心代码
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                path[i][j]=min(path[i][j],path[i][k]+path[k][j]);
            }
        }
    }
    for(i=1;i<=n;i++)//寻找最小代价
    {
        t=0;
        for(j=1;j<=n;j++)
        {
            t+=fri[j]*path[i][j];
        }
        if(ans>t)
        {
            ans=t;
            city=i;
        }
    }
    printf("%d\n%d",city,ans);
    return 0;
}
/**************************************************************
    Language: C++
    Result: 正确
    Time:83 ms
    Memory:1284 kb
****************************************************************/
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值