诶,去年场上不会处理$0$的环,只拿了$60$有点可惜。

我们先不管边边权为$0$的边。

我们先跑一次最短路,令$dis[u]$表示从$1$至$u$的最短路的长度。

那么根据题目的要求,从起点走到$u$号点的路径长度只可能在区间$[dis[u],dis[u]+k]$中。

令$f[i][j]$表示当前从起点走到$i$,行走的路程为$dis[i]+j$的方案数。

不妨发现这个东西可以通过类似分层图最短路的方式进行更新,然后就直接更新就行了。

然而这一题中有部分点存在边权为$0$的边,一旦走入一个$0$环的话采用上述的方法会$TLE$。

于是我们把上面的通过分层图最短路的更新方式,更换为记忆化搜索,我们在当前搜索的路径上打上标记,然后若走到之前标记过的点,那么直接输出$-1$退出即可。这种方式可以有效避免将无需经过的零环纳入考虑范围内。

(可能是个人写法的原因),经过$1$的零环需要特判,直接在最短路里判掉就好了。

然后就没了。时间复杂度:$O(mk+m log n)$。

  1. #include<bits/stdc++.h>
  2. #define M 100005
  3. using namespace std;
  4.  
  5. struct edge{int u,v,next;}e[M*]={}; int head[M]={},head1[M]={},use=;
  6. void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
  7. void add1(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head1[x];head1[x]=use;}
  8. int n,m,k,MOD;
  9.  
  10. struct node{
  11. int x,dis;
  12. node(){x=dis=;}
  13. node(int xx,int ddis){x=xx; dis=ddis;}
  14. friend bool operator <(node a,node b){return a.dis>b.dis;}
  15. }a[M];
  16. priority_queue<node> q;
  17. int vis[M]={},dis[M]={},v[M][]={},f[M][]={},in[M][]={};
  18. int dij(){
  19. q.push(node(,));
  20. while(!q.empty()){
  21. node U=q.top(); q.pop();
  22. int u=U.x;
  23. if(vis[u]) continue;
  24. vis[u]=; dis[u]=U.dis;
  25. for(int i=head[u];i;i=e[i].next){
  26. if(dis[u]+e[i].v==&&e[i].u==) return ;
  27. if(!vis[e[i].u]) q.push(node(e[i].u,dis[u]+e[i].v));
  28. }
  29. }
  30. return ;
  31. }
  32.  
  33. int dfs(int x,int p){
  34. if(f[x][p]!=-) return f[x][p];
  35. if(in[x][p]) return -;
  36. int res=; in[x][p]=;
  37. for(int i=head1[x];i;i=e[i].next){
  38. int v=dis[x]-dis[e[i].u]+p-e[i].v;
  39. if(<=v&&v<=k){
  40. int now=dfs(e[i].u,v);
  41. if(now==-) return -;
  42. res=(res+now)%MOD;
  43. }
  44. }
  45. f[x][p]=res; in[x][p]=;
  46. return res;
  47. }
  48.  
  49. int Main(){
  50. memset(vis,,sizeof(vis)); memset(dis,,sizeof(dis));
  51. memset(f,-,sizeof(f)); memset(e,,sizeof(e));
  52. memset(head,,sizeof(head)); memset(head1,,sizeof(head1)); use=;
  53. memset(in,,sizeof(in));
  54. memset(v,,sizeof(v));
  55. scanf("%d%d%d%d",&n,&m,&k,&MOD);
  56. for(int i=;i<=m;i++){
  57. int x,y,z; scanf("%d%d%d",&x,&y,&z);
  58. add(x,y,z);
  59. add1(y,x,z);
  60. }
  61. if(dij()==){printf("-1\n"); return ;}
  62. int ans=; f[][]=;
  63. for(int i=;i<=k;i++){
  64. int now=dfs(n,i);
  65. if(now==-){
  66. printf("-1\n");
  67. return ;
  68. }
  69. ans=(ans+now)%MOD;
  70. }
  71. printf("%d\n",ans);
  72. }
  73.  
  74. int main(){
  75. int cas; cin>>cas;
  76. while(cas--) Main();
  77. }

【NOIP2017】逛公园 最短路+DP的更多相关文章

  1. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  2. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  3. [NOIP2017] 逛公园 解题报告(DP)

    我很不想说 在我的AC代码上我打了表,但实在没有办法了.莫名的8,9个点RE.然而即便是打表...也花了我很久. 这大概是NOIP2017最难的题了,为了让不懂的人更容易理解,这篇题解会比较详细 我的 ...

  4. [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)

    题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...

  5. 洛谷 P3953 [ NOIP 2017 ] 逛公园 —— 最短路DP

    题目:https://www.luogu.org/problemnew/show/P3953 主要是看题解...还是觉得好难想啊... dfs DP,剩余容量的损耗是边权减去两点最短路差值...表示对 ...

  6. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

  7. [NOIP2017] 逛公园

    [NOIP2017] 逛公园 题目大意: 给定一张图,询问长度 不超过1到n的最短路长度加k 的1到n的路径 有多少条. 数据范围: 点数\(n \le 10^5\) ,边数\(m \le 2*10^ ...

  8. 【比赛】NOIP2017 逛公园

    考试的时候灵光一闪,瞬间推出DP方程,但是不知道怎么判-1,然后?然后就炸了. 后来发现,我只要把拓扑和DP分开,中间加一个判断,就AC了,可惜. 看这道题,我们首先来想有哪些情况是-1:只要有零环在 ...

  9. NOIP2017逛公园(dp+最短路)

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

随机推荐

  1. 客户端、服务器端中JSON字符串与对象的转换

    客户端: 字符串转为对象:$.parseJSON(json); 对象转为字符串:JSON.stringify(_pasteDataItem) 服务器端(c#): 对象: [DataContract(N ...

  2. 首页焦点图myFocus插件

    首页焦点图myFocus插件   myFocus特性 小巧却高效强大 myFocus v2.0.min版只有9.89KB,却能使你的网页上可以运行超过30款风格各异的焦点图,在互联网独一无二哦~ 极其 ...

  3. c++编程思想里面的错误(可能c++标准变了,所以以前的东西没有更新)

    第一卷  第五章 5.3友元 下面的代码是<c++编程思想>里面的代码, struct X; struct Y{ void f(X*); }; struct X{ private: int ...

  4. 557. Reverse Words in a String III

    static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...

  5. 2018.08.30 NOIP模拟 kfib(矩阵快速幂+exgcd)

    [输入] 一行两个整数 n P [输出] 从小到大输出可能的 k,若不存在,输出 None [样例输入 1] 5 5 [样例输出] 2 [样例解释] f[0] = 2 f[1] = 2 f[2] = ...

  6. chandy-lamport 分布式一致性快照 算法详细介绍

    在一个分布式计算系统中,为了保证数据的一致性需要对数据进行一致性快照.Flink和spark在做流失计算的时候都借鉴了chandy-lamport算法的原理,这篇文章就是对chandy-lamport ...

  7. 动态渲染的input怎么取消记忆功能

    方法1 :自定义去除记忆功能属性: $('#index_table_filter > label > input[type="search"]').attr('auto ...

  8. AngularJS标准Web业务流程开发框架-4.AngularJS四大模块之一:Controller

    一.Controller的创建 angular.controller("name",funtion($scope){ }) 1.name:控制器的名称(建议参考Java包的命名规范 ...

  9. 测试-LoadRunner

    1录脚本 设置解析方式,html形式,会精炼成一个函数,此时找有用的url,写出函数:url方式,函数比较多. 参数化 两参数成对时,在脚本处选成对. 加上进程,加上返回值判断. 最后一段接口url, ...

  10. (KMP灵活运用 利用Next数组 )Theme Section -- hdu -- 4763

    http://acm.hdu.edu.cn/showproblem.php?pid=4763 Theme Section Time Limit: 2000/1000 MS (Java/Others)  ...