洛谷 P1144 最短路計數 做題記錄

coding_goat_qwq發表於2024-11-22

前置芝士: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;
}

相關文章