[ABC319G] Counting Shortest Paths
Genius_Star · · 题解
2023/9/22 修改了被 after_contest 制裁的题解(感谢大佬 zhongpeilin,ran_qwq,OIerLKL2578 的帮助)
题意:
现在又一个
思路:
赛后第一次切 G 题诶!
看到这里,大家可能会想到 P1144 最短路计数,直接暴力删边直接做的话,可以使用 BFS 来求,但是这样的时间复杂度也是
其实有一个挺简单的做法,定义
我们从一号点开始入队(初始肯定定义
如果当前队为空了,我们需要加入新的点了,遍历这
现在想想为什么要这样?
我们知道
还有如果
更新
因为
最后我们的答案就是
因为是按照层次分的,所以时间复杂度为:
新增部分:
因为有模数,所以可能
我这里新设置的模式是 after_contest 卡
完整代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200200;
const ll mod=(998244353ll)*(998244353ll);
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
ll n,m,sum=0;
ll dis[N],f[N],s[N];
vector<ll> E[N];
queue<ll> q;
void add(ll u,ll v){ //建边
E[u].push_back(v);
E[v].push_back(u);
}
int main(){
n=read(),m=read();
for(int u,v,i=1;i<=m;i++){
u=read(),v=read();
add(u,v);
}
q.push(1);
dis[1]=1;
f[1]=1;
while(!q.empty()){
ll u=q.front();
q.pop();
for(auto v:E[u]) //删除的边
s[v]=(s[v]+f[u])%mod;
sum=(sum+f[u])%mod; //累加条数
if(q.empty()){ //增点
for(ll i=1;i<=n;i++){
if(!dis[i]&&s[i]!=sum){
dis[i]=dis[u]+1;
f[i]=(sum-s[i]+mod)%mod;
q.push(i);
}
s[i]=0;
}
sum=0;
}
}
if(!f[n])
puts("-1");
else
write(f[n]%998244353ll);
return 0;
}