[NOIP 2017 day1] the park

Title Description

Policy-making students especially like the park. Park can be seen as an  N  points  have sides forming the M to FIG, loopback and without heavy side. Wherein  . 1  dot is an inlet park,  N  dot export park, each side has a non-negative weight value that represents the policy plan after this time it will take sides.

Policy-making will go to the park every day, he was always the  one  to go dot, from  N  out of the dot.

Policy-making like new things, he does not want the park for two days exactly the same route, while making policy or a particular love for the boy to learn, every day he does not want to spend too much time in the park on this matter. If  . 1  point number to  N  dots of the shortest length  d, then the policy strategy will prefer a length not exceeding  d + K  route.

Policy-making students want to know how many routes to meet the conditions of the total, can you help him?

To avoid excessive output, the answer to the  P modulo.

If there are an infinite number of legitimate route, output  -1 .

Input Format

The first row contains an integer  T , represents the number of data sets.

Next  T sets of data, for each set of data:

The first row contains four integers  N, M, K, P  separated by a space between each of the two integers.

Next  M rows, each row of three integers  A I , B I , C I , the representative number  A I , B I  has a weight of between one point  C I  directed edge, each separated by a space between two integers.

Output Format

Output file contains  T  lines, each integer represents the answer.

A closer look at this question can be found to be a DP although I did not see it test , first find the shortest path to either 1 point (Dijkstra, SPFA, Floyd later) start d (on) p (shoot), sub-state dp [u] [k] from the representative node u to node No. 1 is the path length DIS [u] (u 1 to the shortest) + k is the number of paths,

Transfer equation: Σdp [v] [dis [u] - dis [v] + k - edge (u, v)] (dfs anti FIG run, seeking dp [n] [0 ~ k]), and then judged what has there is no "0" ring can be.

On the code:

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int MAX = 1e5 + 10;
struct node{
    int pre, to, val;
}edge[2 * MAX];
int head[MAX], tot;
int dis[MAX], dp[MAX][51];
bool vis[MAX], vis2[MAX][51];
int a[2 * MAX], b[2 * MAX], c[2 * MAX];
int T, n, m, k, p, ans;
bool zero;
void insert(int u, int v, int len) {
    edge[++tot] = node{head[u], v, len};
    head[u] = tot;
}
int read() {
    int ret = 0;
    char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar();
    return ret;
}
priority_queue<pair<int, int> > q;
void dijkstra() {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[1] = 0;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int x = q.top().second;
        q.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        for (int i = head[x]; i; i = edge[i].pre) {
            int y = edge[i].to, z = edge[i].val;
            if (dis[y] > dis[x] + z) {
                dis[y] = dis[x] + z;
                q.push(make_pair(-dis[y], y));
            }
        }
    }
}
int dfs(int x, int now_k) {
    if (dp[x][now_k] != -1) return dp[x][now_k];
    vis2[x][now_k] = 1;
    dp[x][now_k] = 0;
    for (int i = head[x]; i; i = edge[i].pre) {
        int y = edge[i].to, z = edge[i].val;
        int next_k = dis[x] - dis[y] + now_k - z;
        if (next_k < 0) continue;
        if (vis2[y][next_k]) zero = 1;
        dp[x][now_k] += dfs(y, next_k);
        //cout << dp[x][now_k] << endl;
        if (dp[x][now_k] > p) dp[x][now_k] -= p;
    }
    vis2[x][now_k] = 0;
    return dp[x][now_k];
}
int main() {
    T = read();
    while (T--) {
        memset(head, 0, sizeof(head));
        memset(dp, -1, sizeof(dp));
        memset(vis2, 0, sizeof(vis2));
        tot = 0;
        ans = 0;
        zero = 0;
        n = read(), m = read(), k = read(), p = read();
        for (int i = 1; i <= m; i++) {
            a[i] = read(), b[i] = read(), c[i] = read();
            insert(a[i], b[i], c[i]);
        }
        dijkstra();
        memset(head, 0, sizeof(head));
        tot = 0;
        for (int i = 1; i <= m; i++) {
            insert(b[i], a[i], c[i]);
        }
        dp[1][0] = 1;
        for (int i = 0; i <= k; i++) {
            ans += dfs(n, i);
            //puts("");
            if (ans > p) ans -= p;
        }
        dfs(n, k + 1);
        if (zero) {
            puts("-1");
            continue;
        }
        cout << ans << "\n";
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/zcr-blog/p/11480038.html