2017湖南多校第一场-B(1002): Bones’s Battery

Problem B | limit 5 seconds

Bones’s Battery

Bones is investigating what electric shuttle is appropriate for his mom’s school district vehicle.
Each school has a charging station. It is important that a trip from one school to any other be
completed with no more than K rechargings. The car is initially at zero battery and must always
be recharged at the start of each trip; this counts as one of the K rechargings. There is at most
one road between each pair of schools, and there is at least one path of roads connecting each pair
of schools. Given the layout of these roads and K, compute the necessary range required of the
electric shuttle.
Input
Input begins with a line with one integer T (1 T 50) denoting the number of test cases. Each
test case begins with a line containing three integers N, K, and M (2 N 100, 1 K 100),
where N denotes the number of schools, K denotes the maximum number of rechargings permitted
per trip, and M denotes the number of roads. Next follow M lines each with three integers ui, vi,
and di (0 ui; vi < N, ui 6= vi, 1 di 109) indicating that road i connects schools ui and vi
(0-indexed) bidirectionally with distance di.
Output
For each test case, output one line containing the minimum range required.
Sample Input Sample Output
2
4 2 4
0 1 100
1 2 200
2 3 300
3 0 400
10 2 15
0 1 113
1 2 314
2 3 271
3 4 141
4 0 173
5 7 235
7 9 979
9 6 402
6 8 431
8 5 462
0 5 411
1 6 855
2 7 921
3 8 355
4 9 113
300
688

解题思路:先用floyd跑一遍求得最短路,再二分电量,用dp[i][j]表示i到j需充电的次数,在用floyd对dp跑一遍,找出dp中最大值,跟k进行比较,最后得出答案

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
#define INF 100000000000L
LL dist[105][105];
LL dp[105][105];
int n,k,m;

void init()
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        dist[i][j]=INF;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        dp[i][j]=INF;
}

void floyd1()
{
    for(int i=0;i<n;i++)
        dist[i][i]=0;
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
}

void floyd2()
{
    for(int i=0;i<n;i++)
        dp[i][i]=0;
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {

        scanf("%d%d%d",&n,&k,&m);
        init();
        int u,v,d;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&d);
            dist[u][v]=dist[v][u]=d;
        }
        floyd1();
        LL Min=1,Max=INF;
        LL ans=Max;
        LL Mid;
        while(Min<=Max)
        {
            Mid=(Min+Max)/2;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                dp[i][j]=dist[i][j]<=Mid?1:INF;
            floyd2();
            LL d=0;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                if(dp[i][j]>d) d=dp[i][j];
            if(d<=k)
            {
                ans=Mid;
                Max=Mid-1;
            }else
            {
                Min=Mid+1;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值