zoukankan      html  css  js  c++  java
  • P3953 逛公园(dp,最短路)

    P3953 逛公园

    题目描述

    策策同学特别喜欢逛公园。公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。

    策策每天都会去逛公园,他总是从1号点进去,从NN号点出来。

    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到NN号点的最短路长为dd,那么策策只会喜欢长度不超过d + Kd+K的路线。

    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

    为避免输出过大,答案对PP取模。

    如果有无穷多条合法的路线,请输出-11。

    输入输出格式

    输入格式:

    第一行包含一个整数 TT, 代表数据组数。

    接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,PN,M,K,P,每两个整数之间用一个空格隔开。

    接下来MM行,每行三个整数a_i,b_i,c_iai,bi,ci,代表编号为a_i,b_iai,bi的点之间有一条权值为 c_ici的有向边,每两个整数之间用一个空格隔开。

    输出格式:

    输出文件包含 TT 行,每行一个整数代表答案。

    输入输出样例

    输入样例#1: 复制
    2
    5 7 2 10
    1 2 1
    2 4 0
    4 5 2
    2 3 2
    3 4 1
    3 5 2
    1 5 3
    2 2 0 10
    1 2 0
    2 1 0
    输出样例#1: 复制
    3
    -1
    
    

    说明

    【样例解释1】

    对于第一组数据,最短路为 33。 $1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5$ 为 33 条合法路径。

    【测试数据与约定】

    对于不同的测试点,我们约定各种参数的规模不会超过如下

    测试点编号  TT   NN   MM   KK   是否有0边
    1 5 5 10 0
    2 5 1000 2000 0
    3 5 1000 2000 50
    4 5 1000 2000 50
    5 5 1000 2000 50
    6 5 1000 2000 50
    7 5 100000 200000 0
    8 3 100000 200000 50
    9 3 100000 200000 50
    10 3 100000 200000 50

    对于 100%的数据, 1 le P le 10^9,1 le a_i,b_i le N ,0 le c_i le 10001P109,1ai,biN,0ci1000。

    数据保证:至少存在一条合法的路线。

    #include<bits/stdc++.h>
    
    #define b 1000007
    #define ll long long
    
    using namespace std;
    ll n,m,k,p,ans,cnt;
    ll head[b],dis[b],C[b];
    ll vis[b];
    struct edge{
        ll u,v,net,w;
    }e[b<<1];
    queue<ll>q;
    
    inline void add(int u,int v,int w)
    {
        e[++cnt].v=v;e[cnt].w=w;e[cnt].net=head[u];head[u]=cnt;
    }
    
    inline ll read()
    {
        ll x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void spfa(int u)
    {
        dis[u]=0;vis[u]=1;C[u]=1;q.push(u);
        while(!q.empty())
        {
            int now=q.front();q.pop();
            vis[now]=0;
            for(int i=head[now];i;i=e[i].net)
            {
                int v=e[i].v;
                if(dis[v]>dis[now]+e[i].w)
                {
                    dis[v]=dis[now]+e[i].w;
                    C[v]=C[u];
                    if(!vis[v]) vis[v]=1,q.push(v);
                }
                else if(dis[v]==dis[now]+e[i].w) 
                {
                    if(!vis[v]) vis[v]=1,q.push(v);
                    C[v]+=C[u];C[v]%=p;
                }
            }
        }
    }
    
    void clear()
    {
        memset(C,0,sizeof C);
        memset(dis,127/3,sizeof dis);
        memset(vis,0,sizeof vis);
        memset(head,0,sizeof head);
        memset(e,0,sizeof e);
        while(!q.empty()) q.pop();
        cnt=0;
    }
    
    int main()
    {
        int T;T=read();
        while(T--)
        {
            clear();
            n=read();m=read();k=read();p=read();
            int x,y,z;
            for(int i=1;i<=m;i++)
            {
                x=read();y=read();z=read();
                add(x,y,z);
            }
            spfa(1);C[n]%=p;
            cout<<C[n]<<endl;
        }
    }
    20暴力
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<queue>
    
    #define N 200007
    
    using namespace std;
    int T,b,n,m,k,mod,cnt,head[N];
    int from[N],to[N],w[N];
    int dis[N],vis[N],dp[N][51];
    int in[N],re[N],flag;
    struct edge{
        int next,to,w;
    }e[N<<1];
    queue<int>q;
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void add(int x,int y,int w)
    {
        e[++cnt]=(edge){head[x],y,w};
        head[x]=cnt;
    }
    
    int DFS(int x,int res)//返回到达x点还剩res步可以绕的方案数
    {
        if(~dp[x][res]) return dp[x][res];
        dp[x][res]=(x==1);
        for(int i=head[x];i;i=e[i].next)
        {
            int R=e[i].to;
            int tt=res-((dis[R]+e[i].w)-dis[x]);//通过这条边多绕了一会
            if(tt<0) continue;
            if(in[R]&&re[R]==tt) flag=1;//如果说res一直没有减少的情况下搜出来一个圈,说明有0环
            else in[R]=1,re[R]=tt;
            (dp[x][res]+=DFS(R,tt))%=mod;
            in[R]=0;re[R]=0;
        }
        return dp[x][res];
    }
    void Work()
    {
        memset(head,0,sizeof(head));cnt=0;
        b=read();m=read();k=read();mod=read();
        for(int i=1;i<=m;i++)
        {
            from[i]=read();to[i]=read();w[i]=read();
            add(from[i],to[i],w[i]);
        }
        
        memset(dis,63,sizeof(dis));
        q.push(1);dis[1]=0;vis[1]=1;
        while(!q.empty())
        {
            int x=q.front();
            for(int i=head[x];i;i=e[i].next)
            {
                int R=e[i].to;
                if(dis[R]<=dis[x]+e[i].w) continue;
                dis[R]=dis[x]+e[i].w;
                if(!vis[R]) vis[R]=1,q.push(R);
            }
            q.pop();vis[x]=0;
        }
    
        memset(head,0,sizeof(head));cnt=0;
        memset(dp,-1,sizeof(dp));flag=0;
        for(int i=1;i<=m;i++)
            add(to[i],from[i],w[i]);
        DFS(b,k);
        printf("%d
    ",flag?-1:DFS(b,k));
    }
    int main()
    {
        T=read();
        while(T--)Work();  
        return 0;
    }
  • 相关阅读:
    How to Use .Net Remoting Using C#
    How to: Build a Client Application
    C# 禁用鼠标中间键
    秒杀系统:设计方案与实现思路
    JDBC连接数据库
    Java调用webService示例
    spring MVC
    rust贪吃蛇
    初识智遥工作流软件——表单开发篇2
    初识智遥工作流软件——表单开发篇1
  • 原文地址:https://www.cnblogs.com/L-Memory/p/9792317.html
Copyright © 2011-2022 走看看