嘟嘟嘟

这道题他会卡spfa,不过据说加SLF优化后能过,但还是讲讲正解吧。

题中有很关键的一句,就是无向边都是正的,只有单向边可能会有负的。当把整个图缩点后,有向边只会连接在每一个联通块之间(因为图中没有环),而且缩点后的图一定是一个DAG,DAG的最短路就可以拓扑排序后直接求出最短路。

因此,对于每一个联通块内,我们可以dijkstra跑最短路:除了常规的更新以外,每一次跑的时候都要先把这个块内的所有点都放进优先队列中,因为有的点可能已经从别的联通块更新了。然后对于一条边u->v,如果u,v在一个联通块内,就正常更新,否则是更新dis[y],不把他放进队列,而是把y所在的联通块的入度--,如果为0,就放进拓扑序的队列中。

直到拓扑序的队列空。

对于有些走不到的点,可能在INF上加上了一个负数,因此最后判断是否能走到不能dis[i] = INF?,我就是稍微把这个上界放小一点,但又大于最远的dis,于是判断dis[i] > INF / 2?。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. using namespace std;
  12. #define enter puts("")
  13. #define space putchar(' ')
  14. #define Mem(a) memset(a, 0, sizeof(a))
  15. typedef long long ll;
  16. typedef double db;
  17. const int INF = 0x3f3f3f3f;
  18. const db eps = 1e-;
  19. const int maxn = 2.5e4 + ;
  20. inline ll read()
  21. {
  22. ll ans = ;
  23. char ch = getchar(), last = ' ';
  24. while(!isdigit(ch)) {last = ch; ch = getchar();}
  25. while(isdigit(ch)) {ans = ans * + ch - ''; ch = getchar();}
  26. if(last == '-') ans = -ans;
  27. return ans;
  28. }
  29. inline void write(ll x)
  30. {
  31. if(x < ) x = -x, putchar('-');
  32. if(x >= ) write(x / );
  33. putchar(x % + '');
  34. }
  35.  
  36. int n, r, p, s;
  37. vector<int> v[maxn], c[maxn];
  38. vector<int> blo[maxn];
  39.  
  40. int col[maxn], cnt = ;
  41. void dfs(int now)
  42. {
  43. col[now] = cnt; blo[cnt].push_back(now);
  44. for(int i = ; i < (int)v[now].size(); ++i)
  45. if(!col[v[now][i]]) dfs(v[now][i]);
  46. }
  47.  
  48. int in[maxn];
  49. queue<int> topo;
  50.  
  51. #define pr pair<int, int>
  52. #define mp make_pair
  53. int dis[maxn];
  54. bool inq[maxn];
  55. void dijkstra(int bl)
  56. {
  57. Mem(inq);
  58. priority_queue<pr, vector<pr>, greater<pr> > q;
  59. for(int i = ; i < (int)blo[bl].size(); ++i) q.push(mp(dis[blo[bl][i]], blo[bl][i]));
  60. while(!q.empty())
  61. {
  62. int now = q.top().second; q.pop();
  63. if(inq[now]) continue;
  64. inq[now] = ;
  65. for(int i = ; i < (int)v[now].size(); ++i)
  66. {
  67. int to = v[now][i];
  68. if(col[now] == col[to])
  69. {
  70. if(dis[to] > dis[now] + c[now][i])
  71. {
  72. dis[to] = dis[now] + c[now][i];
  73. q.push(mp(dis[to], to));
  74. }
  75. }
  76. else
  77. {
  78. if(dis[to] > dis[now] + c[now][i]) dis[to] = dis[now] + c[now][i];
  79. if(!--in[col[to]]) topo.push(col[to]);
  80. }
  81. }
  82. }
  83. }
  84.  
  85. int main()
  86. {
  87. n = read(); r = read(); p = read(); s = read();
  88. for(int i = ; i <= r; ++i)
  89. {
  90. int x = read(), y = read(), co = read();
  91. v[x].push_back(y); c[x].push_back(co);
  92. v[y].push_back(x); c[y].push_back(co);
  93. }
  94. for(int i = ; i <= n; ++i) if(!col[i]) ++cnt, dfs(i);
  95. for(int i = ; i <= p; ++i)
  96. {
  97. int x = read(), y = read(), co = read();
  98. v[x].push_back(y); c[x].push_back(co);
  99. if(col[x] != col[y]) in[col[y]]++;
  100. }
  101. for(int i = ; i <= cnt; ++i) if(!in[i]) topo.push(i);
  102. for(int i = ; i <= n; ++i) dis[i] = INF; dis[s] = ;
  103. while(!topo.empty()) dijkstra(topo.front()), topo.pop();
  104. for(int i = ; i <= n; ++i) dis[i] > (INF >> ) ? printf("NO PATH\n") : (write(dis[i]), enter);
  105. return ;
  106. }

[USACO11JAN]Roads and Planes的更多相关文章

  1. [USACO11JAN]Roads and Planes G【缩点+Dij+拓补排序】

    题目 Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条道路 (1 < ...

  2. P3008 [USACO11JAN]Roads and Planes G 拓扑排序+Dij

    题目描述 Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条道路 (1 & ...

  3. 【图论】USACO11JAN Roads and Planes G

    题目内容 洛谷链接 Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到\(T\)个城镇 (\(1 <= T <= 25,000\)),编号为\(1\)到\ ...

  4. P3008 [USACO11JAN]Roads and Planes G (最短路+拓扑排序)

    该最短路可不同于平时简单的最短路模板. 这道题一看就知道用SPFA,但是众所周知,USACO要卡spfa,所以要用更快的算法. 单向边不构成环,双向边都是非负的,所以可以将图分成若干个连通块(内部只有 ...

  5. P3008 [USACO11JAN]道路和飞机Roads and Planes

    P3008 [USACO11JAN]道路和飞机Roads and Planes Dijkstra+Tarjan 因为题目有特殊限制所以不用担心负权的问题 但是朴素的Dijkstra就算用堆优化,也显然 ...

  6. Luogu 3008 [USACO11JAN]道路和飞机Roads and Planes

    BZOJ2200 听说加上slf优化的spfa的卡过,真的不想写这些东西. 考虑使用堆优化的dij算法. 先加上所有双向边,然后dfs一下搜出所有由双向边构成的联通块,然后加上所有的单向边,一边对所有 ...

  7. 总结-一本通提高篇&算竞进阶记录

    当一个人看见星空,就再无法忍受黑暗 为了点亮渐渐沉寂的星空 不想就这样退役 一定不会鸽の坑 . 一本通提高篇 . 算竞进阶 . CDQ & 整体二分 . 平衡树 . LCT . 字符串 . 随 ...

  8. poj 1251 Jungle Roads (最小生成树)

    poj   1251  Jungle Roads  (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...

  9. Jungle Roads[HDU1301]

    Jungle Roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

随机推荐

  1. 删除Panl控件中窗体的方法

    //删除窗体方法 private void CloseFrm() { foreach (Control item in panel1.Controls) { if (item is Form) //判 ...

  2. spss C# 二次开发 学习笔记(六)——Spss统计结果的输出

    Spss的二次开发可以很简单,实例化一个对象,然后启用服务,接着提交命令,最后停止服务. 其中重点为提交命令,针对各种统计功能需求,以及被统计分析的数据内容等,命令的内容可以很复杂,但也可以简单的为一 ...

  3. 关于JAVA项目报表选型过程

    本人一直在走.NET技术路线,考虑到后期公司搞JAVA项目,也算是进行技术灾备,开始对JAVA技术进行关注.万事开头难,也是上来一头包.没办法,顶着上吧.上面开始分给我任务了.就是对后期项目报表进行方 ...

  4. 《JavaWeb从入门到改行》关于BaseServlet那些事

    @为什么需要BaseServlet?  我们知道一个POST或者GET提交对应着一个Servlet, 无数的提交会让Servlet页面增加,我们希望一个Servlet就能处理很多提交的请求. @Bas ...

  5. JS判断两个数是否能除尽

    function judgeDivisor(m, n) { var num = {}; var i = 0; var x = parseInt(m / n); m = m % n; var resul ...

  6. COCI2017-2018-2 San

    题意 有\(n \leq 40\)个节点,每个节点有权值\(H \leq 1e9\)和贡献\(v \leq 1e9\),从任意一个点可以向右跳到一个权值不小于它的节点,并获得该点贡献 可以从任意一个点 ...

  7. Bootstrap 在线引用

    Bootstrap 3.3.0 js 文件 <script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.j ...

  8. maven(12),排除冲突JAR包

     JAR包冲突 <dependencies> <dependency> <groupId>org.springframework</groupId> ...

  9. 哪个HTML5内建对象用于在画布上绘制?()

    哪个HTML5内建对象用于在画布上绘制?() getContent getContext getGraphics getCanvas 我的理解: A.C.D不存在HTML5,,js方法中 HTML 5 ...

  10. OS考研复习笔记——操作系统的定义、目标、作用和发展的主要动力

    计算机系统由硬件和软件两部分组成.操作系统(OS,Operating System)是配置在计算机硬件上的第一层软件,是对硬件系统的首次补充. 硬件:计算机物理设备,即各种处理机存储器.输入/输出设备 ...