1. 程式人生 > 其它 >#10064. 「一本通 3.1 例 1」黑暗城堡

#10064. 「一本通 3.1 例 1」黑暗城堡

blackpink yyds

這道題目還是很有意思的,叫什麼最短路徑生成樹。

顯然的一個做法就是用類似於prim的方法,維護一個已經和1聯通的集合以及所有點到1的最短路

然後按照距離dis的距離進行列舉,每次從集合裡找到可以在加進去之後令新點補全。

然後這個過程可以懶得維護,直接檢查每一個點和他周圍點就行了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define int long long
using namespace std;
int n, m;
queue<int> q;
int dis[1000001];
struct ed {
    int to;
    int v;
} tem;
vector<ed> v[1001];
int x, y, z;
int vis[1001];
int mod = (1 << 31) - 1;
void spfa() {
    int s = 1;
    q.push(s);

    memset(dis, 0x7f, sizeof(dis));
    dis[s] = 0;

    while (!q.empty()) {
        int x = q.front();
        q.pop();
        vis[x] = 0;

        for (int i = 0; i < v[x].size(); ++i) {
            int vv = v[x][i].to;

            if (dis[vv] > dis[x] + v[x][i].v) {
                dis[vv] = dis[x] + v[x][i].v;

                if (!vis[vv]) {
                    q.push(vv);
                    vis[vv] = 1;
                }
            }
        }
    }
}
int ans = 1;
signed main() {
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &x, &y, &z);
        v[y].push_back((ed) {
            x, z
        });
        v[x].push_back((ed) {
            y, z
        });
    }

    spfa();

    for (int i = 2; i <= n; ++i) {
        int cnt = 0;

        for (int j = 0; j < v[i].size(); ++j) {
            if (dis[i] == dis[v[i][j].to] + v[i][j].v) {
                cnt++;
            }
        }

        ans *= cnt;
        ans %= mod;
    }

    cout << ans;
    return 0;
}