AcWing 349 Dijkstra

题意

传送门 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;
}

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/114365475