loj #2316

最短路 + 记忆化
记忆化搜索更容易实现


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>

using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10;
const int oo = (1 << 30);

int head1[N], head2[N], cnt;
struct Node {int v, w, nxt;} G1[M], G2[M];

#define gc getchar()
inline int read() {int x = 0; char c = gc; while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;}
#undef gc

int n, m, k, Mod;
int dis[N];
bool vis[N];
int f[N][55];
bool c[N][55];

inline void Link(int u, int v, int w) {
    ++ cnt;
    G1[cnt].v = v, G1[cnt].w = w, G1[cnt].nxt = head1[u], head1[u] = cnt;
    swap(u, v);
    G2[cnt].v = v, G2[cnt].w = w, G2[cnt].nxt = head2[u], head2[u] = cnt;
}

void Init() {
    cnt = 0;
    for(int i = 1; i <= n; i ++) head1[i] = head2[i] = -1;
    memset(f, -1, sizeof f);
    memset(c, 0, sizeof c);
    for(int i = 1; i <= m; i ++) {
        int u = read(), v = read(), w = read();
        Link(u, v, w);
    }
}

int Q[N << 2];

struct Node_ {
    int u, dis_;
    bool operator < (Node_ a) const {
        return dis_ > a.dis_;
    }
};

priority_queue <Node_> Que;

void Dij() {
    for(int i = 1; i <= n; i ++) vis[i] = 0, dis[i] = oo;
    dis[1] = 0;
    Que.push((Node_) {1, 0});
    while(!Que.empty()) {
        Node_ top_ = Que.top();
        Que.pop();
        if(vis[top_.u]) continue;
        vis[top_.u] = 1;
        int u = top_.u;
        for(int i = head1[u]; ~ i; i = G1[i].nxt) {
            int v = G1[i].v;
            if(dis[v] > dis[u] + G1[i].w) {
                dis[v] = dis[u] + G1[i].w;
                Que.push((Node_) {v, dis[v]});
            }
        }
    }
}

bool flag;

int Dp(int u, int K) {
    if(flag == 0) return 0;
    if(~ f[u][K]) return f[u][K];
    f[u][K] = 0, c[u][K] = 1;
    for(int i = head2[u]; ~ i; i = G2[i].nxt) {
        int v = G2[i].v;
        int t = dis[u] + K - dis[v] - G2[i].w;
        if(t < 0) continue;
        if(c[v][t]) {flag = 0; return 0;}
        (f[u][K] += Dp(v, t)) %= Mod;
    }
    c[u][K] = 0;
    return f[u][K];
}

void Solve() {
    Dij();
    f[1][0] = 1;
    int Ans = 0;
    flag = 1;
    for(int i = 0; i <= k; i ++) {
        (Ans += Dp(n, i)) %= Mod;
        if(flag == 0) {
            cout << "-1" << "\n";
            return ;
        }
    }
    cout << Ans << "\n";
}

int main() {
    for(int T = read(); T; T --) {
        n = read(), m = read(), k = read(), Mod = read();
        Init();
        Solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shandongs1/p/9635000.html