题意
有一个图,其中如果两个点之间的最短路是奇数,我们就称它为不和谐最短路,求出每个点经过了几条不和谐最短路。
思路
一开始想到用
d
i
j
k
s
t
r
a
dijkstra
dijkstra跑最短路然后记录前驱递归回去,结果看了别人的讨论发现想法错了。最短路的长度虽然相同,但它可能经过不同的点,所以这种方法是错误的。
跑
S
P
F
A
SPFA
SPFA求多源最短路(
d
i
j
k
s
t
r
a
dijkstra
dijkstra常数大会超时),然后用搜索求每个点经过不和谐最短路的数量。
代码
#include<queue>
#include<cstdio>
#include<cstring>
struct edgeNode{
int to, next, w;
}e[6001];
int n, m, tot;
int head[1001], d[1001][1001], ans[1001], v[1001];
void add(int u, int v, int w) {
e[++tot].to = v;
e[tot].next = head[u];
e[tot].w = w;
head[u] = tot;
}
void SPFA(int s) {
std::queue<int> q;
memset(v, 0, sizeof(v));
memset(d[s], 127 / 3, sizeof(d[s]));
d[s][s] = 0;
v[s] = 1;
q.push(s);
while (q.size()) {
int x = q.front();
q.pop();
v[x] = 0;
for (int i = head[x]; i; i = e[i].next) {
int y = e[i].to;
if (d[s][x] + e[i].w < d[s][y]) {
d[s][y] = d[s][x] + e[i].w;
if (!v[y]) {
v[y] = 1;
q.push(y);
}
}
}
}
}
int dfs(int s, int p) {
int result = d[s][p] & 1, sonResult;
ans[p] += result;
for (int i = head[p]; i; i = e[i].next)
if (d[s][p] + e[i].w == d[s][e[i].to]) {//只走最短路
result += (sonResult = dfs(s, e[i].to));
ans[p] += sonResult;
}
return result;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1, x, y, z; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
for (int i = 1; i <= n; i++)
SPFA(i);
for (int i = 1; i <= n; i++)
dfs(i, i);
for (int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
}