题目描述
给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1∼N。问从顶点 1 开始,到其他每个点的最短路有几条。
输入描述
第一行包含 2 个正整数 N,M,为图的顶点数与边数。
接下来 M 行,每行两个正整数 x,y,表示有一条顶点 x 连向顶点 y 的边,请注意可能有自环与重边。
输出描述
输出 N 行,每行一个非负整数,第 i 行输出从顶点 1 到顶点 i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出 mod100003 后的结果即可。如果无法到达顶点 i 则输出 0。
样例输入
5 7 1 2 1 3 2 4 3 4 2 3 4 5 4 5
样例输出
1 1 1 2 4
这道题需要用到广搜,与动态规划结合求解
它求的是最短路,没有边权,所以说这里我们走到当前边的路径长度,就设为前一个点的最短路径加1,其实也就是求边权都是1的图的最短路径
接着就是说统计路径数量,我们画个图来分析一下
所以说,当前点的最短路径总数,就是所有入边最短路径总数之和
剩下的步骤,就和广搜没什么差异了
#include<bits/stdc++.h>
#define mod 100003
using namespace std;
const int N=5e6+5;
vector<int>a[N];
int n,m;
int dis[N];
int vis[N];
int dp[N];
queue<int>q;
void bfs(){
dis[1]=0;//1号点走到1号点只要零步
dp[1]=1;//走到底一个点只有一种
q.push(1);//起点入队
vis[1]=1;//标记起点
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=0;i<a[x].size();i++){//找出边
int v=a[x][i];
if(vis[v]==0){
vis[v]=1;
dis[v]=dis[x]+1;//当前点的最短路径长度
q.push(v);
}
if(dis[v]==dis[x]+1){
dp[v]=(dp[x]+dp[v])%mod;//状态转移
}
}
}
}
signed main(){
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);//无向图,所以要反着再入一次
}
bfs();
for(int i=1;i<=n;i++)printf("%d\n",dp[i]);
}