PS:如果读过题了可以跳过题目描述直接到题解部分
提交链接:洛谷 P8312 [COCI2021-2022#4] Autobus
在一个国家里有 n n n 座城市。这些城市由 m m m 条公交线路连接,其中第 i i i 条线路从城市 a i a_i ai 出发,到 b i b_i bi 停止,路程中耗时 t i t_i ti 分钟。
Ema 喜欢旅行,但她并不喜欢在公交线路之间换乘。在旅行过程中,她希望最多只需坐 k k k 个不同的公交线路。
Ema 想知道,从城市 c i c_i ci 到城市 d i d_i di 的最短旅行时间是多少(最多坐 k k k 个不同的公交线路)。
第一行包含两个整数 n , m n,m n,m,分别表示城市的数量和公交车线路的数量。
接下来 m m m 行,第 i + 1 i+1 i+1 包含三个整数 a i , b i , t i a_i,b_i,t_i ai,bi,ti,分别表示第 i i i 条公交车线路的起点、终点和从起点到终点所需的时间。
接下来一行包含两个整数 k , q k,q k,q,最大坐的不同公交线路的个数和问题题的个数。
接下来 q q q 行,第 m + j + 3 m+j+3 m+j+3 行包含两个整数 c j , d j c_j,d_j cj,dj,表示询问从城市 c j c_j cj 到城市 d j d_j dj 的最短旅行时间。
输出包含 q q q 行,第 i i i 行包含一个整数,表示从城市 c i c_i ci 到城市 d i d_i di 的最短旅行时间。
4 7
1 2 1
1 4 10
2 3 1
2 4 5
3 2 2
3 4 1
4 3 2
1 3
1 4
4 2
3 3
10
-1
0
4 7
1 2 1
1 4 10
2 3 1
2 4 5
3 2 2
3 4 1
4 3 2
2 3
1 4
4 2
3 3
6
4
0
4 7
1 2 1
1 4 10
2 3 1
2 4 5
3 2 2
3 4 1
4 3 2
3 3
1 4
4 2
3 3
3
4
0
【样例解释】
每个样例中的答案都已经标记在图中。
【数据规模与约定】
本题采用子任务捆绑测试。
对于 100 % 100\% 100% 的数据, 2 ≤ n ≤ 70 , 1 ≤ m , t i ≤ 1 0 6 , 1 ≤ a i , b i , c j , d j ≤ n , 1 ≤ k ≤ 1 0 9 , 1 ≤ q ≤ n 2 2\le n \le 70,1\le m,t_i\le 10^6,1\le a_i,b_i,c_j,d_j\le n,1\le k\le10^9,1\le q \le n^2 2≤n≤70,1≤m,ti≤106,1≤ai,bi,cj,dj≤n,1≤k≤109,1≤q≤n2。
【提示与说明】
本题分值按 COCI 原题设置,满分 70 70 70。
题目译自 COCI2021-2022 CONTEST #4 T2 Autobus。
O ( n 5 ) O(n^5) O(n5)
在floyd中循环更新的次数。
O ( n 4 ) O(n^4) O(n4)
因为每次更新一定比上一次更优,所以我们先循环更新的次数再循环floyd。(注意连边的时候就是第一次更新了)
//洛谷 P8312 [COCI2021-2022#4] Autobus
#pragma GCC optimize(3)
#include
#include
#include
using namespace std;
const int x=0x3f3f3f3f;
int n,m;
int u,v,t;
int r[75][75][75];
int k,q;
int a[75][75];
void in(int &x){
int nt;
x=0;
while(!isdigit(nt=getchar()));
x=nt^'0';
while(isdigit(nt=getchar())){
x=(x<<3)+(x<<1)+(nt^'0');
}
}
void pre(){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
for(int l=1;l<=n;++l){
for(int o=1;o<=k;++o){
for(int p=1;p<=k-o;++p){
r[j][l][o+p]=min(r[j][l][o+p],r[j][i][o]+r[i][l][p]);
if(r[j][l][o+p]<a[j][l]){
a[j][l]=r[j][l][o+p];
}
}
}
}
}
}
}
int main(){
register int i;
in(n),in(m);
memset(r,x,sizeof(r));
memset(a,x,sizeof(a));
for(i=1;i<=n;++i){
a[i][i]=r[i][i][1]=0;
}
for(i=1;i<=m;++i){
in(u),in(v),in(t);
if(u==v){
continue;
}
a[u][v]=r[u][v][1]=min(r[u][v][1],t);
}
in(k),in(q);
k=min(k,n);
pre();
for(i=1;i<=q;++i){
in(u),in(v);
if(a[u][v]==x){
printf("-1\n");
}
else{
printf("%d\n",a[u][v]);
}
}
return 0;
}
//洛谷 P8312 [COCI2021-2022#4] Autobus
#pragma GCC optimize(3)
#include
#include
#include
using namespace std;
const int x=0x3f3f3f3f;
int n,m;
int u,v,t;
int r[75][75];
int k,q;
int a[75][75];
int b[75][75];
void in(int &x){
int nt;
x=0;
while(!isdigit(nt=getchar()));
x=nt^'0';
while(isdigit(nt=getchar())){
x=(x<<3)+(x<<1)+(nt^'0');
}
}
void pre(){
for(int o=1;o<=k-1;++o){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
b[i][j]=a[i][j];
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
for(int l=1;l<=n;++l){
b[j][l]=min(b[j][l],a[j][i]+r[i][l]);
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
a[i][j]=b[i][j];
}
}
}
}
int main(){
register int i;
in(n),in(m);
memset(r,x,sizeof(r));
memset(a,x,sizeof(a));
for(i=1;i<=n;++i){
a[i][i]=r[i][i]=0;
}
for(i=1;i<=m;++i){
in(u),in(v),in(t);
if(u==v){
continue;
}
a[u][v]=r[u][v]=min(r[u][v],t);
}
in(k),in(q);
k=min(k,n);
pre();
for(i=1;i<=q;++i){
in(u),in(v);
if(a[u][v]==x){
printf("-1\n");
}
else{
printf("%d\n",a[u][v]);
}
}
return 0;
}