方法一:这种发放适合于只求最短路的个数,不能用来输出最短路。
我们直接在spfa的过程中使用cnt[]数组记录最短路的个数,用dijkstra也可以!
更新cnt分情况:
- 如果dis[next]>dis[now]+1
那么之前到达点next的路>dis[now]+1
cnt[next]=cnt[now] - 如果dis[next]==dis[now]+1
那么之前到达点next的路也有距离为dis[now]+1的点。
cnt[next]+=cnt[now]
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int
const int maxn=1e6+5;
vector<int> v[maxn];
int dis[maxn],vis[maxn];
int cnt[maxn];
int N,M,mod=100003;
//最短路的个数
void spfa()
{
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(1);
vis[1]=1;
dis[1]=0;
cnt[1]=1;
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(res i=0;i<v[x].size();i++){
int y=v[x][i];
if(dis[y]>dis[x]+1){
dis[y]=dis[x]+1;
cnt[y]=cnt[x]%mod;
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}else if(dis[y]==dis[x]+1){
cnt[y]+=cnt[x];
cnt[y]%=mod;
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}
}
}
}
int main()
{
scanf("%d%d",&N,&M);
int from,to;
for(res i=0;i<M;i++){
scanf("%d%d",&from,&to);
v[from].push_back(to);
v[to].push_back(from);
}
spfa();
for(res i=1;i<=N;i++){
printf("%d",cnt[i]);
printf("\n");
}
return 0;
}
方法二:可以记录路径,但是很慢
我们可以用vector<int> pre[maxn]记录下每一个节点被最短到达的前一个点的节点序号。因为我们记录的都是前驱,所以我们可以从终点出发。这样遍历到的每一个节点都在最短路上面。然后我们dfs或者bfs,ans+每一个遍历到节点前驱的个数-1。最后输出让ans+1。