洛谷P1144《最短路計數》
阿新 • • 發佈:2020-10-14
原更新日期: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 \bmod 100003\)
輸入輸出樣例
輸入樣例
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], '\n');
}
return 0;
}