当前位置: 代码迷 >> 综合 >> CSUOJ Bones’s Battery(二分)(floyd)
  详细解决方案

CSUOJ Bones’s Battery(二分)(floyd)

热度:14   发布时间:2024-01-09 02:47:03.0

1817: Bones’s Battery

Submit Page    Summary    Time Limit: 5 Sec     Memory Limit: 256 Mb     Submitted: 224     Solved: 68    


Description

    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 ≠ 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

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

Sample Output

300
688

 

 

题意:有几个点,每个点之间有一个路程(其实是所需要的电量),保证整张图联通,然后有t次充电的机会,在每一个点都可以选择充满电,但最多充t次电,现在要保证任意每两个点之间都可以相互到达,问电池总容量最小为多少。

这道题本来看样例以为是最短路,想了半天不知道怎么把最短路和电池充电次数联系起来,给于大佬讲了题意之后,于大佬点出可以用二分呀,这才想起来之前monthly spent那道题里的FJ计算最小月花费的二分算法。

先在整张图跑一遍floyd,找出两点之间的最短路,然后开始二分。每次尝试的x值都要开一个新的数组dis,然后如果两点之间的最短路小于x,说明一次充满电可以跑完这两点,在dis中记为1,否则记为inf。

然后在dis中再跑一遍floyd。

如果结果的dis中发现有两点之间需要大于t次充电才能达到的地方说明x不满足,否则x是满足的。

这道题卡了有40分钟,一直以为是二分好久不写了,最后取得的mid那里有bug,一直调,还是WA。最后将ing从0x3f3f3f3f改成了1e9就过了,看来这道题会卡100000000,0x3f3f3f3还是不够大,尤其是这里用开了longlong的情况。

 

 

#include<iostream>
#include<stdio.h>
#include<cstring>
#include <cstring>
#define M 10
#define inf 10000000000
using namespace std;long long m[115][115];bool qwewqtrwet(long long x,int time,int n)
{long long dis[115][115];memset(dis,0,sizeof(dis));//for(int k=1;k<=n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(i!=j){if(m[i][j]<=x)dis[i][j]=1;elsedis[i][j]=inf;}elsedis[i][j]=0;for(int k=0;k<n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(i!=j&&i!=k&&j!=k)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(dis[i][j]>time) return 0;return 1;
}int main()
{int casen;scanf("%d",&casen);while(casen--){memset(m,0,sizeof(m));int n,k,road;long long low=0,high=inf;scanf("%d%d%d",&n,&k,&road);for(int i=0;i<n;i++)for(int j=0;j<n;j++)m[i][j]=inf;for(int i=0;i<n;i++)m[i][i]=0;for(int i=0;i<road;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);high+=z;m[x][y]=z;m[y][x]=z;}for(int k=0;k<n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(i!=j&&i!=k&&j!=k)m[i][j]=min(m[i][j],m[i][k]+m[k][j]);while(low!=high){long long  mid=(low+high)>>1;if(qwewqtrwet(mid,k,n))  high=mid;else low=mid+1;}cout<<low<<endl;}return 0;
}