CodeForces - 1529F It‘s a bird! No, it‘s a plane! No, it‘s AaParsa!(最短路+思维建图)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1529F It‘s a bird! No, it‘s a plane! No, it‘s AaParsa!(最短路+思维建图)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出 n n n 个点(从 0 0 0 开始编号)和 m m m 条边的有向带权图,不过 m m m 条边是动态的,经过 t t t 秒后,第 i i i 条边就从 a i − > b i , c i a_i->b_i,c_i ai−>bi,ci 变成了 a i − > ( b i + t ) m o d n , c i a_i->(b_i+t)\\mod{n},c_i ai−>(bi+t)modn,ci,现在要求输出任意两点之间的最短路(最短路矩阵)
注意:在达到某个点后可以选择停留任意时刻再继续赶路
题目分析:读完题后不难建出分层图最短路的模型,共有 n ∗ n n*n n∗n 个点和 m ∗ n m*n m∗n 条边,直接跑 Floyd 的话是 O ( n 6 ) O(n^6) O(n6),跑 n n n 次 Dijkstra 的话是 O ( n ∗ m ∗ n ∗ l o g ( n ∗ n ) ) = O ( n 4 l o g n ) O(n*m*n*log(n*n))=O(n^4logn) O(n∗m∗n∗log(n∗n))=O(n4logn),所以分层图的想法只能 pass 了
是赛后看题解补的题,发现模型很巧妙,如果没有停留时间的限制,就是一个裸的迪杰斯特拉了(不需要分层图,每个点贪心松弛即可)
加上了停留时间的限制,我们可以对于每个点
i
i
i ,添加一条
i
−
>
(
i
+
1
)
m
o
d
n
,
1
i->(i+1)\\mod n,1
i−>(i+1)modn,1
也就是相邻的两个点添加一条花费为
1
1
1 的道路,为什么这样建图是可行的呢?假设现在点
u
u
u,可以到达点
v
v
v,若我们想要到达点
v
+
k
v+k
v+k 的话,只需要在点
u
u
u 先等上
k
k
k 秒,然后就可以直接走
u
−
>
(
v
+
k
)
u->(v+k)
u−>(v+k) 这条边了,等效于先走
u
−
>
v
u->v
u−>v 然后每一秒依次走
v
−
>
v
+
1
v->v+1
v−>v+1,
v
+
1
−
>
v
+
2
v+1->v+2
v+1−>v+2 等等等等
需要注意的是,第一条边不能走 i − > i + 1 i->i+1 i−>i+1 这条边,所以在写最短路的时候,我们需要手动松弛第一次
还需要注意的是,初始时可能会存在重边(参考样例二),所以我们初始化邻接矩阵时,应该将 i = = j i==j i==j 的位置也初始化为无穷大才行
因为这个题目时间卡的很紧,所以在选择算法的时候需要选择 O ( n 2 ) O(n^2) O(n2) 的迪杰斯特拉,因为在稠密图上跑堆优化的迪杰斯特拉,时间复杂度是 O ( m l o g n ) = O ( n 2 l o g n ) O(mlogn)=O(n^2logn) O(mlogn)=O(n2logn) 的
代码:
// Problem: F. It's a bird! No, it's a plane! No, it's AaParsa!
// Contest: Codeforces - Codeforces Round #722 (Div. 2)
// URL: https://codeforces.com/contest/1529/problem/F
// Memory Limit: 256 MB
// Time Limit: 5000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const LL inf=0x3f3f3f3f3f3f3f3f;
const int N=610;
LL maze[N][N],d[N];
bool vis[N];
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n,m;
read(n),read(m);
memset(maze,0x3f,sizeof(maze));
while(m--) {
int u,v,w;
read(u),read(v),read(w);
maze[u][v]=w;
}
for(int i=0;i<n;i++) {
memset(d,0x3f,sizeof(d));
memset(vis,false,sizeof(vis));
for(int j=0;j<n;j++) {
d[j]=min(d[j],maze[i][j]);
}
while(1) {
LL mmin=inf;
int mark=-1;
for(int j=0;j<n;j++) {
if(!vis[j]&&(mark==-1||d[j]<mmin)) {
mmin=d[j];
mark=j;
}
}
if(mark==-1) {
break;
}
vis[mark]=true;
d[(mark+1)%n]=min(d[(mark+1)%n],d[mark]+1);
for(int j=0;j<n;j++) {
d[(j+d[mark])%n]=min(d[(j+d[mark])%n],d[mark]+maze[mark][j]);
}
}
for(int j=0;j<n;j++) {
if(i==j) {
cout<<0<<' ';
} else {
printf("%lld ",d[j]);
}
}
puts("");
}
return 0;
}
以上是关于CodeForces - 1529F It‘s a bird! No, it‘s a plane! No, it‘s AaParsa!(最短路+思维建图)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 1000B Light It Up(思维)
AC日记——Is it rated? codeforces 807a
B. Just Eat It! CodeForces1285B
Codeforces 1630 E Making It Bipartite 题解 (Dilworth定理)