原更新日期:2019-01-12 09:57:14
最短路“板子”
题目描述
给出一个(N)个顶点(M)条边的无向无权图,顶点编号为(1-N)。问从顶点(1)开始,到其他每个点的最短路有几条。
输入输出格式
输入格式
第一行包含(2)个正整数(N,M),为图的顶点数与边数。
接下来(M)行,每行(2)个正整数(x,y),表示有一条顶点(x)连向顶点(y)的边,请注意可能有自环与重边。
输出格式
共(N)行,每行一个非负整数,第(i)行输出从顶点(1)到顶点(i)有多少条不同的最短路,由于答案有可能会很大,你只需要输出 (ans mod 100003)后的结果即可。如果无法到达顶点(i)则输出(0)。
输入输出样例
输入样例
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
输出样例
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)。
解题思路
稍微改一下最短路板子即可
具体就是用 ans[i]
数组记录一下到i
点的最短路个数,在更新路径长度的时候判一下两条路径长度的关系即可
const int HA = 100006;
/* ... */
for (int e = head[now]; e; e = edge[e].next) {
int to = edge[e].now;
if (dis[to] > dis[now] + edge[e].weight) {
// 两条路径长度不等,更新答案
dis[to] = dis[now] + edge[e].weight;
ans[to] = ans[now];
q.push(NewNode(dis[to], to));
} else if (dis[to] == dis[now] + edge[e].weight) {
// 两条路径长度相等,将答案相加
ans[to] += ans[now];
ans[to] %= HA;
}
}
代码实现
/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>
/* -- External Headers -- */
#include <map>
#include <cmath>
/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)
namespace FastIO {
inline int getint() {
int s = 0, x = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') x = -1;
ch = getchar();
}
while (isdigit(ch)) {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * x;
}
inline void __basic_putint(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10) __basic_putint(x / 10);
putchar(x % 10 + '0');
}
inline void putint(int x, char external) {
__basic_putint(x);
putchar(external);
}
}
namespace Solution {
const int HA = 100003;
struct Graph {
static const int MAXN = 1000000 + 10;
static const int MAXM = 2000000 + 10;
struct Node {
int nweight, now;
Node() { nweight = now = 0; }
bool operator < (const Node &that) const {
return nweight > that.nweight;
}
};
struct Edge {
int now, weight, next;
} edge[MAXM * 2];
int head[MAXN], dis[MAXN], ans[MAXN], cnt;
inline void addEdge(int prev, int next, int weight, bool isR = true) {
if (isR) { addEdge(next, prev, weight, false); }
edge[++cnt].now = next;
edge[cnt].weight = weight;
edge[cnt].next = head[prev];
head[prev] = cnt;
}
inline Node NewNode(int nowWeight, int now) {
Node tmp;
tmp.nweight = nowWeight;
tmp.now = now;
return tmp;
}
inline void SPFA() {
memset(dis, 0x7f, sizeof(dis));
memset(ans, 0, sizeof ans);
std::priority_queue<Node> q;
q.push(NewNode(0, 1));
dis[1] = 0;
ans[1] = 1;
while (!q.empty()) {
Node NowNode = q.top();
q.pop();
int now = NowNode.now;
for (int e = head[now]; e; e = edge[e].next) {
int to = edge[e].now;
if (dis[to] > dis[now] + edge[e].weight) {
dis[to] = dis[now] + edge[e].weight;
ans[to] = ans[now];
q.push(NewNode(dis[to], to));
} else if (dis[to] == dis[now] + edge[e].weight) {
ans[to] += ans[now];
ans[to] %= HA;
}
}
}
}
} g1;
int n, m;
}
signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
freopen("testdata.in", "r", stdin);
freopen("testdata.out", "w", stdout);
#endif
using namespace Solution;
using FastIO::getint;
n = getint();
m = getint();
For (i, 1, m) {
int prev = getint();
int next = getint();
g1.addEdge(prev, next, 1);
}
g1.SPFA();
For (i, 1, n) {
FastIO::putint(g1.ans[i], '
');
}
return 0;
}