最短路计数

题目描述

给出一个 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]);
}

 

posted on 2024-04-06 20:02  fish2012  阅读(7)  评论(0)    收藏  举报  来源