洛谷 P1144 最短路计数 做题记录
前置芝士:bfs,最短路。
思路
因为这张图边权相等,所以 bfs 每一次最先遍历到的点肯定是最短路,所以我们不妨记录一个 \(dis_i\) 表示到 \(i\) 的最短路径,对于当前节点 \(u\),可以到达所有的 \(v\),我们讨论一下:
- 当 \(v\) 未被访问过,那么将 \(v\) 设为已访问,这个点的答案更新为 \(u\),并将它推入搜索队列。
- 当 \(v\) 已经被访问过,仍然加上 \(u\) 的答案,但是不推入搜索队列,因为此时 \(v\) 已经在队列中了。
记得勤取模。
时间复杂度:\(O(n+m)\)。
难点/坑点:无。
点击查看代码
#include<bits/stdc++.h>
#define int i128
#define ll long long
#define i128 __int128
#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
using namespace std;
int read() {
int x=0,f=1; char c=getchar();
for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1);
for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }
const int mod = 100003;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }
#define maxn 1000050
int n,m;
vector<int>G[maxn];
bool vis[maxn];
int cnt[maxn],dis[maxn];
void work() {
in2(n,m);
cnt[1]=1;
For(i,1,m) {
int u,v;
in2(u,v);
pb(G[u],v);
pb(G[v],u);
}
queue<pair<int,int> >q;
q.push({1,0}); vis[1]=1;
while(!q.empty()) {
auto [u,d]=q.front(); q.pop();
for(auto v:G[u]) {
if(!vis[v]) {
vis[v]=1;
q.push({v,d+1});
dis[v]=d+1;
cnt[v]=cnt[u];
}
else if(d+1==dis[v]) (cnt[v]+=cnt[u])%=mod;
}
}
For(i,1,n) cout<<(ll)(cnt[i]%mod)<<'\n';
}
signed main() {
// ios::sync_with_stdio(false);
// cin.tie(0); cout.tie(0);
int _=1;
// int _=read();
For(i,1,_) {
work();
}
return 0;
}
本文来自博客园,作者:coding_goat_qwq,转载请注明原文链接:https://www.cnblogs.com/CodingGoat/p/18562874