题意:
分析:
- 暴力
建分层图,直接跑最短路,把翻转次数当做最短路的状态之一,然后枚举最后的翻转状态
- 正解
我们发现翻转次数最劣情况下会达到 (O(n)) ,所以复杂度成了 (O(n^2))
那么我们考虑如何优化,我们发现一个很显然的结论
当翻转次数超过 (O(log n)) 时,翻转一次的代价远大于遍历一遍整个图
所以我们把跑最短路时的翻转次数分成两部分,一部分是到这个点时至少翻转多少次,另一部分就是从这个点出发翻转多少次
我们把第一部分取掉,然后最短路的状态点数就变成了 (O(18n)) 的,就可以过了
第一部分可以 01BFS 预处理出来,最后枚举翻转了多少次
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define fir first
#define sec second
using namespace std;
namespace zzc
{
inline long long read()
{
long long x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 2e5+5;
const long long mod = 998244353;
const long long inf = 0x3f3f3f3f3f3f;
long long head[maxn],dis[maxn][20],tim[maxn],pw[1000005];
long long n,m,cnt=0,ans;
deque<long long> d;
queue<pii> q;
struct edge
{
int to,nxt,dir;
}e[maxn<<1];
void add(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].dir=w;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void bfs1()
{
memset(tim,0x3f,sizeof(tim));
d.clear();tim[1]=0;
d.push_front(1);
while(!d.empty())
{
int u=d.front();d.pop_front();
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].dir==(tim[u]&1))//ûÓзת
{
if(tim[v]>tim[u])
{
tim[v]=tim[u];
d.push_front(v);
}
}
else
{
if(tim[v]>tim[u]+1)
{
tim[v]=tim[u]+1;
d.push_back(v);
}
}
}
}
}
void bfs2()
{
memset(dis,0x3f,sizeof(dis));
dis[1][0]=0;
q.push(mk(1,0));
while(!q.empty())
{
int u=q.front().fir,w=q.front().sec;q.pop();
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(w+((w&1)!=e[i].dir)>=tim[v]+20) continue;
if(dis[v][w+((w&1)!=e[i].dir)-tim[v]]>dis[u][w-tim[u]]+1)
{
dis[v][w+((w&1)!=e[i].dir)-tim[v]]=dis[u][w-tim[u]]+1;
q.push(mk(v,w+((w&1)!=e[i].dir)));
}
}
}
}
void work()
{
int a,b;
pw[0]=1;ans=inf;
for(int i=1;i<=35;i++) pw[i]=pw[i-1]*2%mod;
for(int i=36;i<=1000000;i++) pw[i]=pw[i-1]*2%mod;
n=read();m=read();
for(int i=1;i<=m;i++)
{
a=read();b=read();
add(a,b,0);add(b,a,1);
}
bfs1();
bfs2();
for(int i=0;i<=20;i++)
{
if(tim[n]+i>20&&ans!=inf) break;
ans=min(ans,pw[i+tim[n]]-1+dis[n][i]);
}
printf("%lld
",ans%mod);
}
}
int main()
{
zzc::work();
return 0;
}