题意
传送门 AcWing 349 黑暗城堡
题解
统计图中最短路径生成树的数量。考虑生成树的过程,以节点 1 1 1 为根,不断加入未加入生成树的节点中最短路最小的节点 i i i,此时保证 i i i 的最短路的前驱节点一定都在生成树中。
使用 D i j k s t r a Dijkstra Dijkstra 求解单源最短路,统计各节点最短路前驱节点的数量,根据乘法原理相乘即得到答案。图为稠密图,使用朴素的 D i j k s t r a Dijkstra Dijkstra,总时间复杂度 O ( N 2 ) O(N^2) O(N2)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1005;
const ll mod = (1LL << 31) - 1;
int N, M, G[maxn][maxn], ds[maxn], cnt[maxn];
bool vs[maxn];
void Dijkstra(int s)
{
memset(ds, 0x3f, sizeof(ds));
memset(vs, 0, sizeof(vs));
ds[s] = 0;
for (int i = 1; i < N; ++i)
{
int x = 0;
for (int j = 1; j <= N; ++j)
if (!vs[j] && (!x || ds[j] < ds[x]))
x = j;
vs[x] = 1;
for (int j = 1; j <= N; ++j)
ds[j] = min(ds[j], ds[x] + G[x][j]);
}
}
int main()
{
scanf("%d%d", &N, &M);
memset(G, 0x3f, sizeof(G));
for (int i = 1; i <= N; ++i)
G[i][i] = 0;
for (int i = 1, x, y, z; i <= M; ++i)
scanf("%d%d%d", &x, &y, &z), G[x][y] = G[y][x] = min(G[x][y], z);
Dijkstra(1);
ll res = 1;
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
if (i != j && ds[i] + G[i][j] == ds[j])
++cnt[j];
for (int i = 2; i <= N; ++i)
res = (res * cnt[i]) % mod;
printf("%lld\n", res);
return 0;
}