洛谷 P1144 最短路计数 题解

P1144 最短路计数

题目描述

给出一个(N)个顶点(M)条边的无向无权图,顶点编号为(1-N)。问从顶点(1)开始,到其他每个点的最短路有几条。

输入格式

第一行包含(2)个正整数(N,M),为图的顶点数与边数。

接下来(M)行,每行(2)个正整数(x,y),表示有一条顶点(x)连向顶点(y)的边,请注意可能有自环与重边。

输出格式

共NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出(ans mod 100003)后的结果即可。如果无法到达顶点(i)则输出(0)

输入输出样例

输入 #1

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

输出 #1

1
1
1
2
4

说明/提示

(1)(5)的最短路有(4)条,分别为(2)(1-2-4-5)(2)(1-3-4-5)(由于(4-5)的边有(2)条)。

对于(20\%)的数据,(N ≤ 100)

对于(60\%)的数据,(N ≤ 1000)

对于(100\%)的数据,(N<=1000000,M<=2000000)

【思路】

最短路 , dijkstra

【题目大意】

从1到每一个点的最短路有多少条

【核心思路】

最短路有多少条?
完全可以在dijkstra或者SPFA的过程中求出来的
因为在松弛操作的时候
用y到x的边去松弛
如果这条边替换上去会使1到x的距离更近
那这个时候x的答案就会变为松到他y的最短路的个数
如果这条边替换上去和原来一样
那就是目前看来可以当做最短路
在x原来最短路个数的基础上加上到点y最短路的个数就可以了

【完整代码】

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;

int read()
{
	int sum = 0,fg = 1;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-')fg = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		sum = sum * 10 + c - '0';
		c = getchar();
	}
	return sum * fg;
}
const int Max = 2000006;
const int mo = 100003;
struct node
{
	int y,ne;
}a[Max << 1];
int head[Max >> 1],sum = 0;

void add(int x,int y)
{
	a[++ sum].y = y;
	a[sum].ne = head[x];
	head[x] = sum;
}

struct point
{
	int x;
	int w;
	bool operator < (const point xx) const
	{
		return xx.w < w;
	}
};
int dis[Max >> 1];
priority_queue<point>q;
int ans[Max >> 1];
bool use[Max >> 1];
void dj()
{
	memset(dis,0x3f,sizeof(dis));
	dis[1] = 0;
	ans[1] = 1;
	q.push((point){1,0});
	while(!q.empty())
	{
		point qwq = q.top();
		q.pop();
		int x = qwq.x,w = qwq.w;
		if(use[x] == true)
			continue;
		else
			use[x] = true;
		for(register int i = head[x];i != 0;i = a[i].ne)
		{
			int awa = a[i].y;
			if(dis[awa] > dis[x] + 1)
			{
				dis[awa] = dis[x] + 1;
				ans[awa] = ans[x];
				if(use[awa] == false)
					q.push((point){awa,dis[awa]});
			}
			else
			if(dis[awa] == dis[x] + 1)
			{
				ans[awa] += ans[x];
				ans[awa] %= mo;
			}
		}
	}
}

int main()
{
	int n = read(),m = read();
	for(register int i = 1;i <= m;++ i)
	{
		int x = read(),y = read();
		add(x,y);
		add(y,x);
	}
	dj();
	for(register int i = 1;i <= n;++ i)
		cout << ans[i] << endl;
	return 0;
}
原文地址:https://www.cnblogs.com/acioi/p/11812959.html