【UOJ#32】【UR #2】跳蚤公路(最短路)

题面

UOJ

题解

不难发现要求的就是是否存在负环。也就是我们只需要找到所有的负的简单环,很容易就可以想到维护路径上和\(x\)相关的内容,即维护一下\(u\)到\(v\)路径上,含有\(kx\)的路径的最小的\(b\)。这个可以用\(Floyd\)在\(O(n^5)\)的复杂度中求解。这样子我们用\(f[u][u][k]\)就知道了一个包含了\(u\)的,且\(x\)系数为\(k\)的最小的环,求出其负环的值域范围,接着其能够到达的所有点都会收到这个负环的限制。

我们的主要目的是找出简单负环,找负环可以用\(Bellman-Ford\)算法,设\(f[t][v]\)表示从\(1\)号点开始走不超过\(t\)步,到达\(v\)的最短路。因为最短路是简单路径,不会有重复点,所谓\(f[t-1][v]=f[t][v]\)。否则如果不等必定存在负环。

注意这个只能检测负环是否存在,我们还要考虑负环会造成的影响,如果一个点\(f[t][v]<f[t-1][v]\),证明这个点受到了负环的影响,同理其所有能够到达的点也能够受到负环的影响。

那么我们把这个想法拓展一步,变为\(f[t][v][k]\),表示走了\(t\)步,到\(v\),\(x\)的系数为\(k\)的最短路。

那么如果存在负环,就要满足:

\[\min\{kx+f[n][v][k]\}\ge \min\{jx+f[n-1][v][j]\}
\]

那么只需要把这个数组搞出来,然后就可以解\(x\)范围了。

窝代码是抄的。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. using namespace std;
  9. #define ll long long
  10. #define MAX 105
  11. #define pi pair<ll,ll>
  12. #define f(i,j,k) f[i][j][k+105]
  13. const ll inf=1e18;
  14. inline int read()
  15. {
  16. int x=0;bool t=false;char ch=getchar();
  17. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  18. if(ch=='-')t=true,ch=getchar();
  19. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  20. return t?-x:x;
  21. }
  22. struct Line{int u,v,w,k;}e[MAX*MAX];int cnt=1;
  23. inline void Add(int u,int v,int w,int k){e[cnt++]=(Line){u,v,w,k};}
  24. int g[MAX][MAX];ll f[MAX][MAX][MAX<<1];
  25. vector<pi> vec[MAX],S;
  26. int n,m;
  27. int main()
  28. {
  29. n=read();m=read();
  30. for(int i=1;i<=m;++i)
  31. {
  32. int u=read(),v=read(),w=read(),k=read();
  33. Add(u,v,w,k);g[u][v]=1;
  34. }
  35. for(int i=1;i<=n;++i)g[i][i]=1;
  36. for(int k=1;k<=n;++k)
  37. for(int i=1;i<=n;++i)
  38. for(int j=1;j<=n;++j)
  39. g[i][j]|=g[i][k]&g[k][j];
  40. for(int i=0;i<=n;++i)
  41. for(int j=1;j<=n;++j)
  42. for(int k=-n;k<=n;++k)
  43. f(i,j,k)=inf;
  44. f(0,1,0)=0;
  45. for(int i=1;i<=n;++i)
  46. {
  47. memcpy(f[i],f[i-1],sizeof(f[i]));
  48. for(int j=1;j<=m;++j)
  49. {
  50. int u=e[j].u,v=e[j].v,w=e[j].w,s=e[j].k;
  51. for(int k=-n;k<=n;++k)
  52. if(f(i-1,u,k)<inf)
  53. f(i,v,k+s)=min(f(i,v,k+s),f(i-1,u,k)+w);
  54. }
  55. }
  56. for(int i=1;i<=n;++i)
  57. for(int k=-n;k<=n;++k)
  58. if(f(n,i,k)!=inf)
  59. {
  60. ll l=-inf,r=inf;bool fl=false;
  61. for(int j=-n;j<=n;++j)
  62. if(f(n-1,i,j)!=inf)
  63. {
  64. if(k>j)r=min(r,(ll)ceil(1.0*(f(n-1,i,j)-f(n,i,k))/(k-j)));
  65. else if(k<j)l=max(l,(ll)floor(1.0*(f(n-1,i,j)-f(n,i,k))/(k-j)));
  66. else if(f(n,i,k)>=f(n-1,i,j)){fl=true;break;}
  67. }
  68. if(!fl&&l<r)vec[i].push_back(make_pair(l,r));
  69. }
  70. for(int i=1;i<=n;++i)
  71. {
  72. S.clear();
  73. for(int j=1;j<=n;++j)
  74. if(g[1][j]&&g[j][i])
  75. for(auto p:vec[j])S.push_back(p);
  76. sort(S.begin(),S.end());
  77. ll l=inf,r=-inf,lst=-inf;
  78. bool fl=false;
  79. for(int j=0,len=S.size();j<len;++j)
  80. {
  81. if(!j&&S[j].first>-inf)
  82. {
  83. l=-inf;r=S[j].first;
  84. fl=true;break;
  85. }
  86. if(lst!=-inf&&lst<=S[j].first)
  87. {
  88. l=lst;r=S[j].first;
  89. fl=true;break;
  90. }
  91. lst=max(lst,S[j].second);
  92. }
  93. if(!fl&&lst<inf)l=lst,r=inf;
  94. if(l==-inf||r==inf||!S.size())puts("-1");
  95. else printf("%lld\n",max(0ll,r-l+1));
  96. }
  97. return 0;
  98. }

【UOJ#32】【UR #2】跳蚤公路(最短路)的更多相关文章

  1. 【UR #2】跳蚤公路

    [UR #2]跳蚤公路 参照yjc方法.也就是地铁环线那个题. 求每个点不在负环内的x的取值范围.然后所有1到j能到i的j的范围取交.得到答案. 每个边形如kx+b的直线,每个环也是 每个点不在负环内 ...

  2. UOJ #32. 【UR #2】跳蚤公路【Floydbellman-ford】

    首先看这个范围很夸张但是其实有限制的也就在1e18*n范围里(走完一圈的边权),然后限制一定是有负环 用Floyd传递闭包,然后设f[i][j][k]为从1走了i步到j并且有k个x的最短路,用B-F处 ...

  3. Solution -「UR #2」「UOJ #32」跳蚤公路

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的带权有向图,每条边还有属性 \(s\in\{-1,0,1\}\).对于每个 \(u ...

  4. 【UOJ #244】【UER #7】短路

    http://uoj.ac/contest/35/problem/244 对其他人来说好简单的一道题,我当时却不会做TWT 注定滚粗啊 题解很好的~ #include<cstdio> #i ...

  5. UOJ 【UR #5】怎样跑得更快

    [UOJ#62]怎样跑得更快 题面 这个题让人有高斯消元的冲动,但肯定是不行的. 这个题算是莫比乌斯反演的一个非常巧妙的应用(不看题解不会做). 套路1: 因为\(b(i)\)能表达成一系列\(x(i ...

  6. UOJ #22 UR #1 外星人

    LINK:#22. UR #1 外星人 给出n个正整数数 一个初值x x要逐个对这些数字取模 问怎样排列使得最终结果最大 使结果最大的方案数又多少种? n<=1000,x<=5000. 考 ...

  7. UOJ.52.[UR #4]元旦激光炮(交互 思路)

    题目链接 \(Description\) 交互库中有三个排好序的,长度分别为\(n_a,n_b,n_c\)的数组\(a,b,c\).你需要求出所有元素中第\(k\)小的数.你可以调用至多\(100\) ...

  8. UOJ【UR #12】实验室外的攻防战

    题意: 给出一个排列$A$,问是否能够经过以下若干次变换变为排列$B$ 变换:若${A_i> A_i+1}$,可以${swap(A_i,A_i+1)}$ 考虑一个数字从A排列到B排列连出来的路径 ...

  9. UOJ Round总结

    #22. [UR #1]外星人 一开始随便搞出第一问答案,很显然的性质对$x$有变化的$a$一定是递减的,就拿一个桶直接记录可以达到的值 然后我开始想第二问,一开始想直接在这个桶上统计答案,然后发现不 ...

随机推荐

  1. 学习shiro第三天

    今天比较晚,所以只看了shiro的认证策略Authentication Strategy,下面讲讲shiro的三种认证策略. 1.AtLeastOneSuccessfulStrategy:这个是shi ...

  2. 结对编程作业(java)

    结对对象:许峰铭 一.Github项目地址:https://github.com/Leungdc/Leungdc/tree/master/%E5%9B%9B%E5%88%99%E8%BF%90%E7% ...

  3. SparkStreaming实战(数据库(NoSQL))

    完全搞清楚项目需求,思考项目选项,这块就是使用的是数据库,就是HBase,因为它里面有一个非常合适的API,直接调用,即可 功能一: 今天到现在为止 实战课程 的访问量 yyyyMMdd 使用数据库来 ...

  4. Linux 初识Libevent网络库

    初识Libevent libevent是用c写的高并发网络io库,只要有文件描述符,就都可使用libevent. libevent使用回调函数(callback) . 有了libevent,网络编程我 ...

  5. 3.2 Spark运行架构

    一.基本概念 1.RDD Resillient Distributed Dataset 弹性分布式数据集 2.DAG 反映RDD之间的依赖关系 3.Executor 进程驻守在机器上面,由进程派生出很 ...

  6. LOJ 3184: 「CEOI2018」斐波那契表示法

    题目传送门:LOJ #3184. 题意简述: 题目说得很清楚了. 题解: 首先需要了解「斐波那契数系」为何物. 按照题目中定义的斐波那契数列 \(F_n\),可以证明,每个非负整数 \(n\) 都能够 ...

  7. Go语言goroutine调度器初始化(12)

    本文是<Go语言调度器源代码情景分析>系列的第12篇,也是第二章的第2小节. 本章将以下面这个简单的Hello World程序为例,通过跟踪其从启动到退出这一完整的运行流程来分析Go语言调 ...

  8. 第十一周博客作业 <西北师范大学| 周安伟>

    第十一周助教作业 助教博客链接https://home.cnblogs.com/u/zaw-315/ 作业要求链接https://www.cnblogs.com/nwnu-daizh/p/107615 ...

  9. CSP前的板子

    板子A(扩展欧几里得) 题目描述 求关于x的同余方程 ax≡1(modb) 的最小正整数解. 输入格式 一行,包含两个正整数 a,b,用一个空格隔开. 输出格式 一个正整数 x​,即最小正整数解.输入 ...

  10. [LeetCode] 239. Sliding Window Maximum 滑动窗口最大值

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...