【题解】ABC319G Counting Shortest Paths
更好的阅读体验
G.Counting Shortest Paths
题目分析:
注意到我们只需要在所有的边都被删完了,再进行询问。
所以可以考虑直接从小到大枚举最短路长度,也就是从
所以一个直观的想法就是一步步预处理出
考虑优化,
对于转移,因为是现在的点对其余所有的点产生贡献,所以可以直接一起转移,只有
设
代码中为了好写,使用了 set 复杂度会变成
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5+5;
const int MOD = 998244353;
set<int> E[N],cur,lst,tmp;
int cnt[N],a[N],tot[N];
signed main(){
int n,m;scanf("%lld%lld",&n,&m);
for(int i=1; i<=m; i++){
int u,v;scanf("%lld%lld",&u,&v);
E[u].insert(v);
E[v].insert(u);
}
cnt[n] = 1;
cur.insert(n);
for(int i=1; i<n; i++) lst.insert(i);
while(!cur.empty()){
int res = 0,res2 = 0;
for(auto now : cur) res = (res + cnt[now])%MOD,res2++;
for(auto to : lst) cnt[to] = (cnt[to] + res)%MOD,tot[to] = 0;
for(auto now : cur){
for(auto to : E[now]){
if(lst.find(to) != lst.end()) //避免奇奇怪怪的相互影响
cnt[to] = (cnt[to] - cnt[now] + MOD)%MOD,tot[to]++;
}
}
for(auto now : cur){
int tot = 0;
for(auto to : E[now]) a[++tot] = to;
for(int i=1; i<=tot; i++){
E[a[i]].erase(now);
E[now].erase(a[i]);
}
}
swap(tmp,lst);
cur.clear(),lst.clear();
for(auto i : tmp){
if(tot[i] != res2){ //tot 其实就是记录一下是不是有点可以转移到他
cur.insert(i);
if(i == 1){
printf("%lld\n",cnt[1]);
return 0;
}
}
else lst.insert(i);
}
tmp.clear();
}
printf("-1\n");
return 0;
}