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;
}

浙公网安备 33010602011771号