策策同学特别喜欢逛公园。公园可以看成一张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;
}

转载于:https://www.cnblogs.com/WWHHTT/p/9903958.html

NOIP 2017 逛公园相关推荐

  1. NOIP 2017 逛公园 记忆化搜索 最短路 好题

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

  2. 【NOIP 2017 提高组】逛公园

    [题目] 传送门 题目描述: 策策同学特别喜欢逛公园.公园可以看成一张 nnn 个点 mmm 条边构成的有向图,且没有自环和重边.其中 111 号点是公园的入口,nnn 号点是公园的出口,每条边有一个 ...

  3. 2017noip逛公园

    2017 noip Day1 T2 逛公园 (洛谷P3953)传送门 输出输入数据自己找 这个题看到其他的大佬有用dp做的. 推荐一个大佬的讲解 本蒟蒻dp学得烂,东拼拼西凑凑勉强懂了.就发一个dfs ...

  4. TYVJ1427 小白逛公园

    P1427 小白逛公园 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦-在小新家附近有一条"公园路&qu ...

  5. 【游记】NOIP 2017

    时间:2017.11.11~2017.11.12 地点:广东省广州市第六中学 Day1 T1:看到题目,心想这种题目也能放在T1? 这个结论我之前遇到过至少3次,自己也简单证明过.初见是NOIP200 ...

  6. JZOJ 5475. 【NOIP2017提高组正式赛】逛公园

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

  7. 牛客小白月赛12 I 华华和月月逛公园 (tarjian 求桥)

    链接:https://ac.nowcoder.com/acm/contest/392/I 来源:牛客网 华华和月月逛公园 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K, ...

  8. 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索

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

  9. 【ybt高效进阶4-4-3】【luogu P4513】公园遛狗 / 小白逛公园

    公园遛狗 / 小白逛公园 题目链接:ybt高效进阶4-4-3 / luogu P4513 题目大意 给你一个序列,要维护两个操作. 单点修改和在一个区间中找权值最大的子区间的权值. 思路 其实这个是很 ...

最新文章

  1. 双调整!清华大学迎来新任书记、校长
  2. 20145328《网络对抗》Web基础
  3. 使用Ant Design 和Vue,React中后台开发套餐
  4. JDK1.8 Lambda 使用详解(转)
  5. Win10怎么设置虚拟内存?
  6. 项目实战|100个蓝牙接收器发货了
  7. 南通大学计算机组成原理期末考试题,南通大学计算机组成原理期末考试范围.docx...
  8. 设置字段权限_命令行快速提示:权限进阶
  9. oracle 修改 回话数,Oracle命令--修改oracle回话数
  10. 【机器学习_2】机器学习资料
  11. 【设计模式】-工厂模式->简单工厂模式(源码与类图解析)
  12. sheng的学习笔记-mysql框架原理
  13. Renew 、Revive 、Renovate、Update、Refresh区别
  14. 小程序转uni-app——引入组件显示问题
  15. 这款耳机的性价比堪比AirPods,写代码的你可以看看
  16. Web基础-JSON和AJAX
  17. Unity3D 2021.1.1F1。更新与下载。
  18. PreTranslateMessage和TranslateMessage区别
  19. 解决windows 2000无法安装vmtool的问题
  20. C语言文件读写操作,写入数据到文件

热门文章

  1. SAP 学习资料和网站
  2. 关于确界的一些知识点
  3. 棋牌软件被恶意攻击应该怎么办
  4. 基于树莓派的智能垃圾桶
  5. (附源码)计算机毕业设计Java二手车车况在线评估
  6. GIT检查是否SSH通畅的指令
  7. XTU 1235 CQRXLB 2015嘉杰信息杯 湘潭赛
  8. 利用Selenium 登录京东,抢购19.9的荣耀手环3
  9. Redis五种基本数据类型(超级详细)
  10. 物联网工程规划与设计