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

    题目描述

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

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

    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N

    号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。

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

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

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

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

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    首先反向边跑dij求每个点到终点最短路,然后记忆化搜索转移。

    注意最后跑一遍搜-1 。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define M 200050
    inline int rd()
    {
        int f = 1,c =  0;char ch = getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=(c<<1)+(c<<3)+ch-'0';ch=getchar();}
        return f*c;
    }
    int T,n,m,K,P,hed[N],cnt,ihed[N],icnt;
    struct EG
    {
        int to,w,nxt;
    }ie[M],e[M];
    void ae(int f,int t,int v)
    {
        e[++cnt].to = t;
        e[cnt].w = v;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void aie(int f,int t,int v)
    {
        ie[++icnt].to = t;
        ie[icnt].w = v;
        ie[icnt].nxt = ihed[f];
        ihed[f] = icnt;
    }
    int dis[N];
    bool vis[N];
    struct node
    {
        int x,d;
        node(){}
        node(int x,int d):x(x),d(d){}
        friend bool operator < (node a,node b)
        {
            return a.d>b.d;
        }
    }tp;
    bool ot;
    /*void ck(int u)
    {
        if(vis[u])
        {
            ot=1;
            return ;
        }
        vis[u]=1;
        for(int j=ihed[u];j;j=ie[j].nxt)
        {
            int to = ie[j].to;
            if(dis[to]>=dis[u]+ie[j].w)
            {
                dis[to]=dis[u]+ie[j].w;
                ck(to);
                if(ot)return ;
            }
        }
        vis[u]=0;
    }*/
    priority_queue<node>q;
    void dij()
    {
        memset(dis,0x3f,sizeof(dis));
        dis[n]=0;
        q.push(node(n,0));
        while(!q.empty())
        {
            tp = q.top();
            q.pop();
            int u = tp.x;
            if(vis[u])continue;
            vis[u]=1;
            for(int j=ihed[u];j;j=ie[j].nxt)
            {
                int to = ie[j].to;
                if(dis[to]>dis[u]+ie[j].w)
                {
                    dis[to]=dis[u]+ie[j].w;
                    q.push(node(to,dis[to]));
                }
            }
        }
    }
    int dp[N][55];
    bool vs[N][55];
    int dfs(int u,int k)
    {
        if(dp[u][k]!=-1)return dp[u][k];
        vs[u][k]=1;
        dp[u][k] = 0;
        for(int to,tmp,j=hed[u];j;j=e[j].nxt)
        {
            to = e[j].to;
            tmp = k-dis[to]+dis[u]-e[j].w;
            if(tmp<0)continue;
            if(vs[to][tmp])ot=1;
            (dp[u][k]+=dfs(to,tmp))%=P;
        }
        vs[u][k]=0;
        return dp[u][k];
    }
    void init()
    {
        memset(hed,0,sizeof(hed));
        memset(ihed,0,sizeof(ihed));
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        memset(dp,-1,sizeof(dp));
        cnt=icnt=0;
        ot=0;
    }
    int main()
    {
        T=rd();
        while(T--)
        {
            init();
            n=rd(),m=rd(),K=rd(),P=rd();
            for(int u,v,w,i=1;i<=m;i++)
            {
                u=rd(),v=rd(),w=rd();
                ae(u,v,w);
                aie(v,u,w);
            }
            dis[n]=1;
    //        ck(n);
    //        if(ot)
    //        {
    //            printf("-1
    ");
    //            continue;
    //        }
            dij();
            dp[n][0]=1;
            int ans = 0;
            for(int k=0;k<=K&&ot==0;k++)
            {
                (ans+=dfs(1,k))%=P;
            }
            dfs(1,K+1);
            if(ot)printf("-1
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    大话设计模式之备忘录模式
    大话设计模式之模板方法模式
    大话设计模式之桥接模式
    大话设计模式之组合模式
    大话设计模式之适配器模式
    大话设计模式之原型模式
    大话设计模式之解释器模式
    大话设计模式之享元模式
    大话设计模式之迭代器模式
    dom操作排他思想
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9743643.html
Copyright © 2011-2022 走看看