题意:
给定一个 n n n个点 m m m条边的无向连通图,求从 1 1 1号点到达每个点的最短路的最短路条数。
数据范围: 1 ≤ n ≤ 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 1\leq n\leq 10^5,1\leq m\leq2\times 10^5 1≤n≤105,1≤m≤2×105
题解:
如果带负权边那么只能考虑 s p f a spfa spfa,否则使用 d i j k s t r a dijkstra dijkstra即可。
由于 s p f a spfa spfa并非按照拓扑序来更新最短路,所以为了更好地解决问题,建议统一先求一遍最短路,然后使用记忆化搜索求到达每个点的最短路条数。特别地,需要初始化到达点 1 1 1的最短路条数为 1 1 1。
代码:
/*dijkstra实现*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
const int M = 4e5 + 10;
const int mod = 100003;
int n, m;
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
struct Node {
int id, d;
bool operator < (const Node &A) const {
return d > A.d;
}
};
priority_queue<Node> q;
int dist[N], cnt[N];
bool st[N];
void dijkstra() {
memset(st, false, n + 1);
memset(dist, 0x3f, n + 1 << 2);
dist[1] = 0;
q.push({
1, 0});
while(!q.empty()) {
Node t = q.top(); q.pop();
int u = t.id;
if(st[u]) continue;
st[u] = true;
for(int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if(dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
q.push({
v, dist[v]});
}
}
}
}
int get(int v) {
if(st[v]) return cnt[v];
st[v] = true;
for(int i = h[v]; ~i; i = ne[i]) {
int u = e[i];
if(dist[v] == dist[u] + w[i]) cnt[v] = (cnt[v] + get(u)) % mod;
}
return cnt[v];
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, n + 1 << 2);
idx = 0;
for(int i = 1; i <= m; ++i) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b, 1);
add(b, a, 1);
}
dijkstra();
memset(st, false, n + 1);
st[1] = true; cnt[1] = 1;
for(int i = 1; i <= n; ++i) printf("%d\n", get(i));
return 0;
}
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
const int M = 4e5 + 10;
const int mod = 100003;
int n, m;
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
queue<int> q;
int dist[N], cnt[N];
bool st[N];
void spfa() {
memset(st, false, n + 1);
memset(dist, 0x3f, n + 1 << 2);
dist[1] = 0;
q.push(1);
st[1] = true;
while(!q.empty()) {
int u = q.front(); q.pop();
st[u] = false;
for(int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if(dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
if(!st[v]) q.push(v), st[v] = true;
}
}
}
}
int get(int v) {
if(st[v]) return cnt[v];
st[v] = true;
for(int i = h[v]; ~i; i = ne[i]) {
int u = e[i];
if(dist[v] == dist[u] + w[i]) cnt[v] = (cnt[v] + get(u)) % mod;
}
return cnt[v];
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, n + 1 << 2);
idx = 0;
for(int i = 1; i <= m; ++i) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b, 1);
add(b, a, 1);
}
spfa();
memset(st, false, n + 1);
st[1] = true; cnt[1] = 1;
for(int i = 1; i <= n; ++i) printf("%d\n", get(i));
return 0;
}