洛谷 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;
}
posted @ 2024-11-22 14:53  coding_goat_qwq  阅读(4)  评论(0编辑  收藏  举报