[ABC319G] Counting Shortest Paths 题解
FReQuenter · · 题解
题意:给定一张
考虑宽搜。但是普通的宽搜要把所有的边都访问一遍,复杂度
计算最短路径的数量:
我们令当前访问的点为
啥意思呢:对于一条边
这个东西转移也是
扩展新的点
我们记录所有没有被搜索到的点,那么搜索到一个新点的时候就可以只对那些没有被搜到且在新图中和当前点相连的点就行了。因为只有那些被删除的边会重复被标记,而其它点只会被标记一次,所以这一部分是
总复杂度
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
#define MAXN 200005
using namespace std;
int n,m,sum[MAXN],f[MAXN],dist[MAXN];
vector<int> rst,gv[MAXN];
bool vis[MAXN];
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
gv[u].push_back(v);
gv[v].push_back(u);
}
for(int i=2;i<=n;i++) rst.push_back(i);
memset(dist,0x3f,sizeof(dist));
dist[1]=0;
f[1]=1;
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.front();
q.pop();
if(u!=1) f[u]=sum[dist[u]-1];
for(auto v:gv[u]){
vis[v]=1;
if(dist[v]==dist[u]-1) f[u]=(f[u]+mod-f[v])%mod;
}
if(u==n) break;
sum[dist[u]]+=f[u],sum[dist[u]]%=mod;
vector<int> tmp;
for(auto nx:rst){
if(vis[nx]) tmp.push_back(nx);
else{
q.push(nx);
dist[nx]=dist[u]+1;
}
}
rst=tmp;
for(auto v:gv[u]) vis[v]=0;
}
if(dist[n]==0x3f3f3f3f3f3f3f3f) cout<<-1;
else cout<<f[n];
}