两遍 spfa 然后建立分层图拓扑排序 dp 一下。

写得很差劲。效率很低。

时间复杂度 \(\mathrm{O}(Tnk)\)。

参见这里秒懂。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <queue>
  5. using namespace std;
  6. int T, n, m, k, p, cnt[2], hea[2][100005], dis[2][100005], uu, vv, ww, he[5100005], cn, dp[5100005];
  7. int ind[5100005], f[100005][55];
  8. bool vis[5100005];
  9. queue<int> d;
  10. struct Edge{
  11. int too, nxt, val;
  12. }edge[2][200005], edg[10200005];
  13. void rn(int &x){
  14. char ch=getchar();
  15. x = 0;
  16. while(ch<'0' || ch>'9') ch = getchar();
  17. while(ch>='0' && ch<='9'){
  18. x = x * 10 + ch - '0';
  19. ch = getchar();
  20. }
  21. }
  22. void add_edge(int rr, int fro, int too, int val){
  23. edge[rr][++cnt[rr]].nxt = hea[rr][fro];
  24. edge[rr][cnt[rr]].too = too;
  25. edge[rr][cnt[rr]].val = val;
  26. hea[rr][fro] = cnt[rr];
  27. }
  28. void add_edg(int fro, int too){
  29. edg[++cn].nxt = he[fro];
  30. edg[cn].too = too;
  31. he[fro] = cn;
  32. }
  33. void init(){
  34. rn(n); rn(m); rn(k); rn(p);
  35. memset(he, 0, sizeof(he));
  36. memset(dp, 0, sizeof(dp));
  37. memset(hea, 0, sizeof(hea));
  38. memset(vis, 0, sizeof(vis));
  39. memset(ind, 0, sizeof(ind));
  40. memset(dis, 0x3f, sizeof(dis));
  41. dis[0][1] = dis[1][n] = cnt[0] = cnt[1] = cn = 0;
  42. dp[1] = 1;
  43. for(int i=1; i<=m; i++){
  44. rn(uu); rn(vv); rn(ww);
  45. add_edge(0, uu, vv, ww);
  46. add_edge(1, vv, uu, ww);
  47. }
  48. int qwq=0;
  49. for(int i=1; i<=n; i++)
  50. for(int j=0; j<=k; j++)
  51. f[i][j] = ++qwq;
  52. }
  53. void spfa(int rr){
  54. d.push(rr?n:1);
  55. vis[rr?n:1] = true;
  56. while(!d.empty()){
  57. int x=d.front();
  58. d.pop();
  59. vis[x] = false;
  60. for(int i=hea[rr][x]; i; i=edge[rr][i].nxt){
  61. int t=edge[rr][i].too;
  62. if(dis[rr][t]>dis[rr][x]+edge[rr][i].val){
  63. dis[rr][t] = dis[rr][x] + edge[rr][i].val;
  64. if(!vis[t]){
  65. vis[t] = true;
  66. d.push(t);
  67. }
  68. }
  69. }
  70. }
  71. }
  72. void build(){
  73. for(int i=1; i<=n; i++)
  74. for(int j=0; j<=k; j++)
  75. if(dis[0][i]+dis[1][i]+j<=dis[0][n]+k)
  76. vis[f[i][j]] = true;
  77. for(int i=1; i<=n; i++)
  78. for(int j=0; j<=k; j++)
  79. if(vis[f[i][j]])
  80. for(int l=hea[0][i]; l; l=edge[0][l].nxt){
  81. int t=edge[0][l].too, v=j+dis[0][i]+edge[0][l].val-dis[0][t];
  82. if(v<=k && f[t][v]){
  83. add_edg(f[i][j], f[t][v]);
  84. ind[f[t][v]]++;
  85. }
  86. }
  87. }
  88. void topsort(){
  89. for(int i=1; i<=n; i++)
  90. for(int j=0; j<=k; j++)
  91. if(vis[f[i][j]] && !ind[f[i][j]])
  92. d.push(f[i][j]);
  93. while(!d.empty()){
  94. int x=d.front();
  95. d.pop();
  96. for(int i=he[x]; i; i=edg[i].nxt){
  97. int t=edg[i].too;
  98. ind[t]--;
  99. if(ind[t]==0) d.push(t);
  100. dp[t] = dp[t]+dp[x]>=p?dp[t]+dp[x]-p:dp[t]+dp[x];
  101. }
  102. }
  103. }
  104. int chk(){
  105. for(int i=1; i<=f[n][k]; i++)
  106. if(ind[i]!=0)
  107. return -1;
  108. int re=0;
  109. for(int i=0; i<=k; i++)
  110. re = re+dp[f[n][i]]>=p?re+dp[f[n][i]]-p:re+dp[f[n][i]];
  111. return re;
  112. }
  113. int main(){
  114. cin>>T;
  115. while(T--){
  116. init();
  117. spfa(0);
  118. spfa(1);
  119. build();
  120. topsort();
  121. printf("%d\n", chk());
  122. }
  123. return 0;
  124. }

luogu3563 逛公园的更多相关文章

  1. [vijos P1083] 小白逛公园

    不知怎地竟有种错觉此题最近做过= =目测是类似的?那道题貌似是纯动归? 本来今晚想做两道题的,一道是本题,一道是P1653疯狂的方格取数或NOI08 Employee,看看现在的时间目测这个目标又达不 ...

  2. Bzoj 1756: Vijos1083 小白逛公园 线段树

    1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1021  Solved: 326[Submit][Statu ...

  3. BZOJ 1756: Vijos1083 小白逛公园

    题目 1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 856  Solved: 264[Submit][Sta ...

  4. JDOJ-P1260 VIJOS-P1083 小白逛公园

    首先,在这里给大家推荐一个网站,https://neooj.com:8082,这是我母校的网站 言归正传,题目描述 VIJOS-P1083 小白逛公园 Time Limit: 1 Sec  Memor ...

  5. [NOIP2017] 逛公园

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

  6. [NOIp 2017]逛公园

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

  7. 【NOIP 2017】逛公园

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

  8. 逛公园 [NOIP2017 D1T3] [记忆化搜索]

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

  9. [luogu P3953] [noip2017 d1t3] 逛公园

    [luogu P3953] [noip2017 d1t3] 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N ...

随机推荐

  1. Python实现两已知排好序的列表合并成一个排好序的列表

    #方法0.5--- lst1 = [1, 3, 7, 9, 12] lst2 = [4, 8, 9, 13, 15, 19] def merge(a, b): c = [] h = j = 0 whi ...

  2. Brush (IV) LightOJ - 1018

    题意:平面上有一些点,每刷一次可以把同一条直线上的点都刷光,问最少几次把所有点刷光. 方法: 显然是一个状态压缩dp.ans[S]表示把S集合中点刷掉的最少次数.最开始想到的方法是如果S中只有一个或两 ...

  3. Reduce实现

    Reduce实现 参考 第一版 Array.prototype.fakeReduce = function (fn, base) { // this 指向原数组 // 拷贝数据, 更改指针方向 var ...

  4. 486 Predict the Winner 预测赢家

    给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,…….每次一个玩家只能拿取一个分数,分数被拿取之后不再可取.直到没有剩余分数 ...

  5. RHEL 6.5---SVN服务实现过程

    主机名 IP地址  master 192.168.30.130 slave 192.168.30.131 安装 [root@master ~]# yum install -y subversion h ...

  6. 【转】在 26 岁时写给 18 岁的自己--Livid

    原文:http://livid.v2ex.com/essays/2012/01/24/a-letter-from-26-to-18/ 我知道现在的自己是再也回不去的了.可是倘若有机会,我是多么希望能让 ...

  7. C#基础学习3

    运算符,表达式!

  8. UVM挑战及概述

    UVM的调度也具有其独特的挑战,尤其是在调试的领域.其中的一些挑战如下: 1. Phase的管理:objections and synchronization 2. 线程调试 3. Tracing i ...

  9. Linux安装技巧--安装Uuntu与windows8/10共存

    1.准备安装双系统所需工具. 系统: Linux有众多的衍生版本,选择一个自己喜欢的版本下载,建议新手上ubuntu吧,中文教程较多,出了问题容易解决,等到熟悉了再用其他的也行,新手的话ubuntu也 ...

  10. https为数据传输保驾护航

    为什么要使用https 谷歌官网已宣布,今年7月起,Chrome浏览器的地址栏将把所有HTTP标示为不安全网站. 在客户端与服务器数据传输过程中,http协议传输是不安全的,一般情况下,http协议的 ...