• NOIP 2017 逛公园


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

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

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

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

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

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


    去年的考试题,考场上没有想到,连DFS都打错了

    首先来看k=0的情况,就是一个裸的最短路计数

    然后是正解,我们有最短路计数可以想到正解肯定是个DP

    dp[i][j]代表的是从1号点到i号点,满足需要比最短路多走j的长度的路线的数量

    因为k的最大值是50,所以可以开状态

    然后来看具体如何实现,我们先SPFA求出单源最短路

    然后反向建图,这样可以避免走进死路

    然后会发现DP直接写并不好实现,因为转移顺序不好确定

    于是想到记忆化搜索,需要那个就转移

    因为DP状态已经设好了

    所以只需要转移,每一次我们对于每条边进行操作

    对于边u->v 权值为w

    我们可以通过刚才求出来的最短路来计算出从1到v还需要多走多长的路

    也就是dis[u]-dis[v]+j-w   j为当前还需要多走的长度   (注意,此时的u,v是在反向图中的)

    然后求和即可

    下面给出代码:(注意赋初值)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline long long rd(){
        long long x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(long long x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    long long n,m,k,mod;
    long long head[1000006];
    long long nxt[2000006],to[2000006];
    long long v[2000006];
    long long total=0;
    void add(long long x,long long y,long long z){
        total++;
        v[total]=z;
        to[total]=y;
        nxt[total]=head[x];
        head[x]=total;
        return ;
    }
    long long q[1000006];
    long long l=0,r=0;
    long long book[1000006];
    long long dis[1000006];
    void spfa(long long x){
        memset(dis,127,sizeof(dis));
        memset(book,0,sizeof(book));
        l=0,r=0;
        book[x]=1;
        dis[x]=0;
        q[++r]=x;
        while(l<r){
            long long h=q[++l];
            book[h]=0;
            for(long long e=head[h];e;e=nxt[e]){
                if(dis[to[e]]>dis[h]+v[e]){
                    dis[to[e]]=dis[h]+v[e];
                    if(!book[to[e]]){
                        q[++r]=to[e];
                        book[to[e]]=1;
                    }
                }
            }
            book[h]=0;
        }
        return ;
    }
    long long f[100006][56];
    long long vis[100006][56];
    long long head2[200006];
    long long to2[200006];
    long long nxt2[200006];
    long long v2[200006];
    long long total2=0;
    void add2(long long x,long long y,long long z){
        total2++;
        to2[total2]=y;
        v2[total2]=z;
        nxt2[total2]=head2[x];
        head2[x]=total2;
        return ;
    }
    long long set=0;
    long long dfs(long long x,long long y){
        if(f[x][y]!=-1) return f[x][y];
        vis[x][y]=1;
        f[x][y]=0;
        for(long long e=head2[x];e;e=nxt2[e]){
            long long h1=to2[e],h2=dis[x]-dis[to2[e]]-v2[e]+y;
            if(h2>=0){
                if(vis[h1][h2]) set=1;
                int num=dfs(h1,h2);
                f[x][y]=(f[x][y]+num)%mod;
            }
        }
        vis[x][y]=0;
        return f[x][y];
    }
    int main(){
        long long T=rd();
        while(T--){
            memset(head,0,sizeof(head));
            memset(head2,0,sizeof(head2));
            total=total2=0;
            n=rd(),m=rd(),k=rd(),mod=rd();
            for(long long i=1;i<=m;i++){
                long long x=rd(),y=rd(),z=rd();
                add(x,y,z),add2(y,x,z);
            }
            spfa(1);
            memset(f,-1,sizeof(f));
            memset(vis,0,sizeof(vis));
            f[1][0]=1;
            long long ans=0;
            set=0;
            for(long long i=0;i<=k;i++){
                ans=(ans+dfs(n,i))%mod;
            }
            dfs(n,k+1);
            if(!set) write(ans%mod),puts("");
            else write(-1),puts("");
        }
        return 0;
    }
  • 相关阅读:
    pycharm中报错:ImportError: No module named 'skimage'
    pycharm 怎么能像在命令行中输入参数进行调试
    python在pycharm中导包一直出错的问题
    安装tensorflow遇到:Your CPU supports instructions that this TensorFlow binary was not compiled to use
    curses is not supported on this machine:(curses 在pycharm(Windows)中的安装 )
    python 2 和python 3 中的编码对比
    用python 遍历文件夹中所有.dcm文件
    pycharm 安装 tensorflow
    如何在Eclipse中写Processing的sketch
    Random Target Moving~
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9903958.html
Copyright © 2020-2023  润新知