洛谷P1144《最短路计数》
作者:互联网
原更新日期: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\)后的结果即可。如果无法到达顶点\(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], '\n');
}
return 0;
}
标签:include,洛谷,int,短路,ans,edge,P1144,now,dis 来源: https://www.cnblogs.com/handwer/p/13816502.html