AtCoder ABC211D Number of Shortest paths 题解

题目简述

给定一张 \(n\) 个点 \(m\) 条边的无向无权图,问从 \(1\)\(n\) 的最短路有多少条。

题目分析

\(cnt_i\) 表示从 \(1\)\(i\) 的最短路条数,\(dis_i\) 表示最短路。

这道题可以考虑使用 BFS 做,对于一个点 \(v\),设第一次更新它的点为 \(u\),则它的转移应为 \(cnt_v \leftarrow cnt_u\) 并且 \(dis_v \leftarrow dis_u+1\),表示 \(v\) 的最短路是由 \(u\) 转移过来的。由于 BFS 的算法流程,此时 \(v\) 的最短路已经被确定下来了,所以之后再有点 \(x\) 更新 \(v\) 时,仅当 \(dis_v=dis_x+1\) 时,才有转移 \(cnt_v \leftarrow cnt_v+cnt_x\),表示 \(1 \rightarrow x \rightarrow v\)\(1 \rightarrow v\) 的另一条最短路。

最后输出 \(cnt_n\) 即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define random(a,b) (rand()%(b-a+1)+a)
const int N=2e5+10,mod=1e9+7;
int n,m,x,y,dis[N],cnt[N],vis[N];
vector<int> G[N]; 
queue<int> q;
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
    	cin>>x>>y;
    	G[x].push_back(y);
    	G[y].push_back(x);
	}
	memset(dis,0x3f,sizeof dis);
	dis[1]=0;
	cnt[1]=1;
	q.push(1);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=1;
		for(int v:G[u])
		{
			if(!vis[v])
			{
				dis[v]=dis[u]+1;
				cnt[v]+=cnt[u];
				q.push(v);
				vis[v]=1;
			}
			else if(dis[u]+1==dis[v])
			{
				cnt[v]=(cnt[v]+cnt[u])%mod;
			}
		}
	}
	cout<<cnt[n];
	return 0;
}
posted @ 2024-04-17 22:56  zhuluoan  阅读(53)  评论(0)    收藏  举报