记录编号 511988 评测结果 AAAAAAAAAA
题目名称 [NOIP 2017]逛公园 最终得分 100
用户昵称 Gravatarサイタマ 是否通过 通过
代码语言 C++ 运行时间 1.878 s
提交时间 2018-10-01 09:21:36 内存使用 114.75 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
class EDGE
{public:
    int u, v, w, next;
}edge[400010], redge[400010];
bool vis[400010], used[400010][51], flag;
int T, n, m, k, p, a, b, c, head[400010], rhead[400010], cnt, rcnt, d[400010], f[400010][51], ans;
void ADDE(int u, int v, int w)
{
    edge[++cnt] = {u, v, w, head[u]};
    head[u] = cnt;
}
void RADDE(int u, int v, int w)
{
    redge[++rcnt] = {u, v, w, rhead[u]};
    rhead[u] = rcnt;
}
void SPFA()
{
    memset(vis, 0, sizeof(vis));
    queue<int> q;
    q.push(1);
    d[1] = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for(int i = head[u]; i; i = edge[i].next)
        {
            int v = edge[i].v;
            int w = edge[i].w;
            if(d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                if(!vis[v])
				{
                	q.push(v);
                	vis[v] = 1;
                }
            }
        }
    }
}
int dfs(int u, int rest)
{
    if(!flag) return 0;
    if(~f[u][rest]) return f[u][rest];
    used[u][rest] = 1;
    f[u][rest] = 0;
    for(int i = rhead[u]; i; i = redge[i].next)
    {

        int v = redge[i].v;
        int w = redge[i].w;
        int nowrest = d[u] - d[v] + rest - w;
        if(nowrest < 0)continue;
        if(used[v][nowrest])
        {
            flag = 0;
            return 0;
        }
        f[u][rest] = (f[u][rest] + dfs(v, nowrest)) % p;
    }
    used[u][rest] = 0;
    return f[u][rest];
}
int main()
{
    freopen("2017park.in", "r", stdin);
    freopen("2017park.out", "w", stdout);
    scanf("%d", &T);
    while(T --)
    {
        cnt = 0;
        rcnt = 0;
        ans = 0;
        flag = 1;
        memset(head, 0, sizeof(head));
        memset(rhead, 0, sizeof(rhead));
        memset(d, 0x7f, sizeof(d));
        memset(used, 0, sizeof(used));
        memset(f, -1, sizeof(f));
        scanf("%d%d%d%d", &n, &m, &k, &p);
        for(int i = 1; i <= m; ++ i)
        {
            scanf("%d%d%d", &a, &b, &c);
            ADDE(a, b, c);
            RADDE(b, a, c);
        }
        SPFA();
        f[1][0] = 1;
        for(int i = 0; i <= k && flag; ++ i)
            ans = (ans + dfs(n, i)) % p;
        if(!flag)
            ans = -1;
        printf("%d\n", ans);
    }
    return 0;
}