其他分享
首页 > 其他分享> > 「LOJ #10064」 黑暗城堡

「LOJ #10064」 黑暗城堡

作者:互联网

知道黑暗城堡有 \(N\) 个房间,\(M\) 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 \(D_i\) 为如果所有的通道都被修建,第 \(i\) 号房间与第 \(1\) 号房间的最短路径长度;
而 \(S_i\) 为实际修建的树形城堡中第 \(i\) 号房间与第 \(1\) 号房间的路径长度;
要求对于所有整数 \(i(1≤i≤N)\),有 \(S_i=D_i\) 成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 \(2^{31}−1\) 取模之后的结果就行了。

Loj

分析

第一步肯定求出 \(1\) 号节点到每个点的最短路,然后考虑建路。

因为要保证建好的路必须使该节点到 \(1\) 号节点的实际路径长度等于最短路长度,所以我们枚举每个点 \(u\) ,与 \(u\) 相连的边集为 \(T\) ,找到 \(edge(u,v)\in T\) ,使得 \(dis[v]=dis[u]+w(u,v)\) 就好了。

找 \(v\) 点的话,在 \(Dijkstra\) 中直接计数就行了。

注意: \(M\) 一定要设为 \(N*N\) 而不是 \(N*N/2\) !!!用 C++(NOI) 编译会显示超时,这可把我坑惨了......

代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1003
#define M N*N
#define il inline
#define re register
#define INF 0x3f3f3f3f
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x) {
    T f = 1; x = 0; char c;
    for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    x *= f;
}

const ll mod = (1ll << 31) - 1ll;

struct edge {
    int to, nxt, v;
} e[M];

int n, m;
ll ret = 1;
int head[M], cnt;
int d[N], ans[N];
bool vis[N];

void insert(int u, int v, int w) {
    e[++cnt].to = v, e[cnt].nxt = head[u], e[cnt].v = w, head[u] = cnt;
}

void Dijkstra() {
    for (int i = 2; i <= n; ++i) d[i] = INF;
    priority_queue < pair<int, int> > q;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int u = q.top().second; q.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to, w = e[i].v;
            if (d[u] + w < d[v]) {
                d[v] = d[u] + w; ans[v] = 1;
                q.push(make_pair(-d[v], v));
            }
            else if (d[u] + w == d[v]) ans[v]++;
        }
    }
}

int main() {
    int u, v, w;
    read(n), read(m);
    for (int i = 1; i <= m; ++i) {
        read(u), read(v), read(w);
        insert(u, v, w), insert(v, u, w);
    }
    Dijkstra();
    for (int i = 1; i <= n; ++i)
        if (ans[i])
            ret = ret * ans[i] % mod;
    printf("%lld", ret);
    return 0;
}

标签:10064,LOJ,城堡,int,read,长度,include,define
来源: https://www.cnblogs.com/hlw1/p/12260565.html