#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;
}
posted @ 2021-07-25 16:09  Simex  阅读(68)  评论(0编辑  收藏  举报