题目描述

策策同学特别喜欢逛公园。 公园可以看成一张 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 行,每行一个整数代表答案。

此题仔细研究一下就可以发现是一道DP虽然我考试时没看出来,先求出1到任一点的最短路(dijkstra,SPFA,Floyd)之后开始d(对)p(拍),子状态dp[u][k]代表从1号节点到u号节点路径长度为dis[u](1到u的最短路) + k的路径条数,

转移方程:∑dp[v][dis[u] - dis[v] + k - edge(u, v)](dfs跑反图,求dp[n][0~k]),再判一下有没有"0"环即可。

上代码:

  1. #include <iostream>
  2. #include <queue>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAX = 1e5 + ;
  6. struct node{
  7. int pre, to, val;
  8. }edge[ * MAX];
  9. int head[MAX], tot;
  10. int dis[MAX], dp[MAX][];
  11. bool vis[MAX], vis2[MAX][];
  12. int a[ * MAX], b[ * MAX], c[ * MAX];
  13. int T, n, m, k, p, ans;
  14. bool zero;
  15. void insert(int u, int v, int len) {
  16. edge[++tot] = node{head[u], v, len};
  17. head[u] = tot;
  18. }
  19. int read() {
  20. int ret = ;
  21. char ch = getchar();
  22. while (!isdigit(ch)) ch = getchar();
  23. while (isdigit(ch)) ret = ret * + ch - '', ch = getchar();
  24. return ret;
  25. }
  26. priority_queue<pair<int, int> > q;
  27. void dijkstra() {
  28. memset(dis, 0x3f, sizeof(dis));
  29. memset(vis, , sizeof(vis));
  30. dis[] = ;
  31. q.push(make_pair(, ));
  32. while (!q.empty()) {
  33. int x = q.top().second;
  34. q.pop();
  35. if (vis[x]) continue;
  36. vis[x] = ;
  37. for (int i = head[x]; i; i = edge[i].pre) {
  38. int y = edge[i].to, z = edge[i].val;
  39. if (dis[y] > dis[x] + z) {
  40. dis[y] = dis[x] + z;
  41. q.push(make_pair(-dis[y], y));
  42. }
  43. }
  44. }
  45. }
  46. int dfs(int x, int now_k) {
  47. if (dp[x][now_k] != -) return dp[x][now_k];
  48. vis2[x][now_k] = ;
  49. dp[x][now_k] = ;
  50. for (int i = head[x]; i; i = edge[i].pre) {
  51. int y = edge[i].to, z = edge[i].val;
  52. int next_k = dis[x] - dis[y] + now_k - z;
  53. if (next_k < ) continue;
  54. if (vis2[y][next_k]) zero = ;
  55. dp[x][now_k] += dfs(y, next_k);
  56. //cout << dp[x][now_k] << endl;
  57. if (dp[x][now_k] > p) dp[x][now_k] -= p;
  58. }
  59. vis2[x][now_k] = ;
  60. return dp[x][now_k];
  61. }
  62. int main() {
  63. T = read();
  64. while (T--) {
  65. memset(head, , sizeof(head));
  66. memset(dp, -, sizeof(dp));
  67. memset(vis2, , sizeof(vis2));
  68. tot = ;
  69. ans = ;
  70. zero = ;
  71. n = read(), m = read(), k = read(), p = read();
  72. for (int i = ; i <= m; i++) {
  73. a[i] = read(), b[i] = read(), c[i] = read();
  74. insert(a[i], b[i], c[i]);
  75. }
  76. dijkstra();
  77. memset(head, , sizeof(head));
  78. tot = ;
  79. for (int i = ; i <= m; i++) {
  80. insert(b[i], a[i], c[i]);
  81. }
  82. dp[][] = ;
  83. for (int i = ; i <= k; i++) {
  84. ans += dfs(n, i);
  85. //puts("");
  86. if (ans > p) ans -= p;
  87. }
  88. dfs(n, k + );
  89. if (zero) {
  90. puts("-1");
  91. continue;
  92. }
  93. cout << ans << "\n";
  94. }
  95. return ;
  96. }

[NOIP 2017 day1]逛公园的更多相关文章

  1. 【NOIP 2017】逛公园

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

  2. NOIP 2017 Day1 解题报告

    总分:100分 T1,小凯的疑惑, 100分 T2,时间复杂度,0分 T3,逛公园,0分 T1 ###题意简化: 给定两个互质的数字,输出最大不能表示的数: 基础数论题目 代码: #include&l ...

  3. [NOIp 2017]逛公园

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

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

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

  5. NOIP2017 Day1 T3 逛公园

    NOIP2017 Day1 T3 更好的阅读体验 题目描述 策策同学特别喜欢逛公园.公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,\(N\)号点 ...

  6. NOIP 2017 解题报告

    ---恢复内容开始--- NOIP 2017 的题真的很难啊,怪不得当年我这个萌新爆零了(当然现在也是萌新)越学越觉得自己什么都不会. 想要成为强者要把这些好题都弄懂弄透 至少现在6道题我都比较陌生 ...

  7. 【游记】NOIP 2017

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

  8. 逛公园「NOIP2017」最短路+DP

    大家好我叫蒟蒻,这是我的第一篇信竞题解blog [题目描述] 策策同学特别喜欢逛公园. 公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园 ...

  9. 逛公园[NOIP2017 D2 T3](dp+spfa)

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

随机推荐

  1. mysqld: [ERROR] Found option without preceding group in config file D:\TONG\mysql-5.7.19-winx64\my.ini at line 1!

    my.ini文件编码不对,改为ANSI 貌似大意是说,配置不全 改编码为ANSI解决

  2. ie使用已安装的最高版本ie代码,及ie下不要在结尾处写多余的逗号“,”

    ie使用已安装的最高版本ie代码 <meta http-equiv = "X-UA-Compatible" content = "IE=7,IE=9" & ...

  3. 「JSOI2010」排名

    「JSOI2010」排名 传送门 看到先后顺序限制和字典序,很容易想到拓扑排序 + 贪心. 考虑具体做法: 对于第一问: 我们开一个大根堆来代替队列,然后从大到小构造出各个元素的排名. 我们连边 \( ...

  4. Python 基础之面向对象之八步理解装饰器

    装饰器:在不改变原有代码的情况下,为该原函数扩展新功能特征:返回新函数,替换旧函数语法:@ 语法糖 1.装饰器原型 #例1: def kuozhan(func):    def newfunc():  ...

  5. Vagrant 安装使用

    先安装虚拟机 https://www.virtualbox.org/ 再安装 https://www.vagrantup.com/  1.nginxhttp://nginx.org/download/ ...

  6. 操作系统OS,Python - 协程(Coroutine)

    留坑 参考: https://en.wikipedia.org/wiki/Coroutine https://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B http ...

  7. [转]:Ubuntu 下Apache安装和配置

    [转]:Ubuntu 下Apache安装和配置_服务器应用_Linux公社-Linux系统门户网站  https://www.linuxidc.com/Linux/2013-06/85827.htm ...

  8. java 并发线程锁

     1.同步和异步的区别和联系 异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回 值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流 ...

  9. A*算法和K短路(A*)

    堪称最好的A算法 https://blog.csdn.net/b2b160/article/details/4057781 K短路(A) https://www.jianshu.com/p/27019 ...

  10. Linux centosVMware运行告警系统、分发系统-expect讲解、自动远程登录后,执行命令并退出、expect脚本传递参数、expect脚本同步文件、指定host和要同步的文件、shell项目-分发系统-构建文件分发系统、分发系统-命令批量执行

    一运行告警系统 创建一个任务计划crontab -e 每一分钟都执行一次 调试时把主脚本里边log先注释掉 再次执行 没有发现502文件说明执行成功了,每日有错误,本机IP 负载不高 二.分发系统-e ...