zoukankan      html  css  js  c++  java
  • [NOIP2017]逛公园

    [NOIP2017]逛公园https://www.luogu.org/problemnew/show/P3953

    题目描述

    策策同学特别喜欢逛公园。公园可以看成一张 (N) 个点 (M) 条边构成的有向图,且没有 自环和重边。其中 (1) 号点是公园的入口,(N) 号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。
    策策每天都会去逛公园,他总是从 (1) 号点进去,从 (N) 号点出来。
    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果 (1)号点到 (N) 号点的最短路长为 (d) ,那么策策只会喜欢长度不超过 (d+K) 的路线。
    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?
    为避免输出过大,答案对 (P) 取模。
    如果有无穷多条合法的路线,请输出(−1)

    输入格式:

    第一行包含一个整数 (T) , 代表数据组数。
    接下来 (T) 组数据,对于每组数据: 第一行包含四个整数 (N,M,K,P,) 每两个整数之间用一个空格隔开。
    接下来 (M) 行,每行三个整数(a_i,b_i,c_i),代表编号为(a_i,b_i)的点之间有一条权值为 (c_i) 的有向边,每两个整数之间用一个空格隔开。

    输出格式:

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

    输入样例:

    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

    输出样例:

    3
    -1

    说明

    样例解释
    对于第一组数据,最短路为 3。 1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5 为 3 条合法路径。

    测试数据与约定
    对于(100)%的数据,$ 1≤P≤10^9,1≤a_i,b_i≤N,0≤c_i≤1000$
    数据保证:至少存在一条合法的路线。


    建反图记忆化搜索
    先一边(Spfa())预处理出最短路(dist[i])
    (dp[i][j])表示从点(1)到点(i)距离等于(dist[i]+j)的路径条数
    有:

    [dp[1][0]=1 ]

    对于一条反边((u,v,w))

    [dp[u][k]=sum dp[v][dist[u]+k-w-dist[v]] ]

    判零环:
    如果一个未确定的(dp)值被经过两次,显然有零环,标记数组(c[i][j])记录即可

    #define RG register
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N=1e5+5,M=2e5+5;
    inline int read()
    {
        RG int x=0,w=1;RG char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    int T,n,K,m,p,cnt,Ans;
    int last[N],Last[N],dist[N],f[N][55];
    bool Flag;
    bool used[N],c[N][55];
    struct edge{int to,next,w;}e[M],E[M];
    queue<int> Q;
    inline void insert(int u,int v,int w)
    {
        cnt++;
        e[cnt]=(edge){v,last[u],w};last[u]=cnt;
        E[cnt]=(edge){u,Last[v],w};Last[v]=cnt;
    }
    inline void init()
    {
        cnt=0;Ans=0;Flag=false;
        memset(last,0,sizeof(last));
        memset(Last,0,sizeof(Last));
        memset(dist,63,sizeof(dist));
        memset(used,false,sizeof(used));
        memset(f,-1,sizeof(f));
        memset(c,false,sizeof(c));
        memset(e,0,sizeof(e));
        memset(E,0,sizeof(E));
    }
    inline void Spfa()
    {
        while(!Q.empty())Q.pop();
        Q.push(1);
        used[1]=true;dist[1]=0;
        while(!Q.empty())
        {
            int now=Q.front();Q.pop();
            used[now]=false;
            for(RG int i=last[now];i;i=e[i].next)
            {
                int v=e[i].to;
                if(dist[v]>dist[now]+e[i].w)
                {
                    dist[v]=dist[now]+e[i].w;
                    if(!used[v])Q.push(v),used[v]=true;
                }
            }
        }
    }
    int dfs(int now,int k)
    {
        if(~f[now][k])return f[now][k];
        c[now][k]=true;
        f[now][k]=0;
        for(RG int i=Last[now];i;i=E[i].next)
        {
            int v=E[i].to;
            int t=dist[now]+k-E[i].w-dist[v];
            if(t<0)continue;
            if(c[v][t])Flag=true;
            f[now][k]+=dfs(v,t);f[now][k]%=p;
        }
        c[now][k]=false;
        return f[now][k];
    }
    int main()
    {
        T=read();
        while(T--)
        {
            init();
            n=read(),m=read(),K=read(),p=read();
            RG int u,v,w;
            for(RG int i=1;i<=m;i++)
            {
                u=read(),v=read(),w=read();
                insert(u,v,w);
            }
            f[1][0]=1;
            Spfa();
            for(RG int i=0;i<=K;i++)Ans+=dfs(n,i),Ans%=p;
            dfs(n,K+1);//判零环[K=0]
            if(Flag){puts("-1");continue;}
            printf("%d
    ",Ans);
        }
        return 0;
    }
    
  • 相关阅读:
    CentOS 6.2安装Darwin Streaming Server
    流媒体技术笔记(协议相关)
    流媒体技术笔记(视频编码相关)
    CentOS6.2下编译mpeg4ip
    用popen函数操作其它程序的输入和输出
    给centos6.2安装yum源
    启动新进程(fork和exec系列函数实现)
    扩展Asterisk1.8.7的Dialplan Applications
    源码安装ffmpeg(带libx264)
    扩展Asterisk1.8.7的AMI接口
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/8639225.html
Copyright © 2011-2022 走看看