题目大意:

  • 求图中两两点对最短距离之和

  • 允许你删除一条边,让你最大化删除这个边之后的图中两两点对最短距离之和。

暴力:每次枚举删除哪条边,以每个点为源点做一次最短路,复杂度\(O(NM^2logN)\)。

值得注意的是,\(Dijkstra\)的复杂度\(O(NlogN)\)是关于边而非点的

这个复杂度对于\(n=100,m=1000\)的数据难以接受。我们考虑对每个点建出其最短路树。容易想到,只有删除到这个点的最短路树上的边时,才需要再做一次\(Dijkstra\)。也就是说每个源点只需要做\(n\)次最短路,复杂度变成\(O(N^2MlogN)\)。

代码实现起来比较麻烦。。本弱调了整整一晚上。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define LL long long
  4. const int N = 100 + 5;
  5. const int M = 2000 + 5;
  6. const int INF = 0x3f3f3f3f;
  7. int n, m, l, kase, ban[M];
  8. struct Graph {
  9. int cnt, head[N];
  10. struct Edge {int from, nxt, to, id, w;}e[M];
  11. void clear () {
  12. cnt = -1;
  13. for (int i = 1; i <= n; ++i) {
  14. head[i] = -1;
  15. }
  16. }
  17. void add_edge (int u, int v, int w) {
  18. ++cnt; e[cnt] = (Edge) {u, head[u], v, cnt, w}; head[u] = cnt;
  19. }
  20. struct HeapNode {
  21. int u; LL d;
  22. bool operator < (HeapNode rhs) const {
  23. return d > rhs.d;
  24. }
  25. };
  26. priority_queue <HeapNode> pq;
  27. int done[N], _fa[N][N]; LL _dis[N][N];
  28. //dis[i][j] -> i to j
  29. //fa[i][j] -> i as source, j's father
  30. void dijkstra (int s) {
  31. kase = kase + 1;
  32. pq.push ((HeapNode) {s, 0});
  33. LL *dis = _dis[s]; int *fa = _fa[s];
  34. for (int i = 1; i <= n; ++i) {
  35. fa[i] = -1, dis[i] = i == s ? 0 : INF;
  36. }
  37. while (!pq.empty ()) {
  38. HeapNode now = pq.top (); pq.pop ();
  39. if (done[now.u] == kase) continue;
  40. for (int i = head[now.u]; ~i; i = e[i].nxt) {
  41. int v = e[i].to;
  42. if (ban[i]) continue;//禁用的边 -> 不用
  43. if (dis[v] > dis[now.u] + e[i].w) {
  44. fa[v] = now.u;
  45. dis[v] = dis[now.u] + e[i].w;
  46. pq.push ((HeapNode) {v, dis[v]});
  47. }
  48. }
  49. done[now.u] = kase;
  50. }
  51. // cout << "s = " << s << endl;
  52. // for (int i = 1; i <= n; ++i) {
  53. // cout << "dis[" << i << "] = " << dis[i] << endl;
  54. // }
  55. }
  56. }G;
  57. bool have[N][M]; int minw[N][N];
  58. struct Tree {
  59. vector <int> Gr[N];
  60. int sz[N]; LL sum[N], dis[N];
  61. //sz[u] -> 点u的子树大小
  62. //sum[u] -> 点u到其子树里所有点的距离和
  63. void prep (int u) {
  64. sz[u] = 1; sum[u] = dis[u];
  65. for (int i = 0; i < (int)Gr[u].size (); ++i) {
  66. int v = Gr[u][i];
  67. prep (v);
  68. sz[u] += sz[v];
  69. sum[u] += sum[v];
  70. }
  71. }
  72. void build (int s, LL *_dis, int *fa, int cmd) {
  73. for (int i = 1; i <= n; ++i) Gr[i].clear ();
  74. memcpy (dis, _dis, sizeof (dis));
  75. for (int i = 1; i <= n; ++i) {
  76. if (fa[i] != -1) {
  77. Gr[fa[i]].push_back (i);
  78. if (cmd == 1) {
  79. have[fa[i]][i] = true;
  80. have[i][fa[i]] = true;
  81. }
  82. }
  83. }
  84. prep (s);
  85. // for (int i = 1; i <= n; ++i) {
  86. // cout << "dis[" << i << "] = " << dis[i] << endl;
  87. // cout << "sum[" << i << "] = " << sum[i] << endl;
  88. // }
  89. }
  90. LL get_ans (int s, LL *_dis, int *fa, int cmd) {
  91. build (s, _dis, fa, cmd);
  92. return sum[s] + (n - sz[s]) * l;
  93. }
  94. }tr[N];//tr[i] -> 点i的最短路树
  95. signed main () {
  96. // freopen ("data.in", "r", stdin);
  97. // freopen ("data.out", "w", stdout);
  98. while (cin >> n >> m >> l) {
  99. G.clear ();
  100. memset (have, 0, sizeof (have));
  101. memset (minw, 0x3f, sizeof (minw));
  102. for (int i = 1; i <= m; ++i) {
  103. static int u, v, w;
  104. cin >> u >> v >> w;
  105. G.add_edge (u, v, w);
  106. G.add_edge (v, u, w);
  107. minw[u][v] = min (minw[u][v], w);
  108. minw[v][u] = min (minw[v][u], w);
  109. }
  110. LL ans1 = 0, ans2 = 0;
  111. for (int s = 1; s <= n; ++s) {
  112. G.dijkstra (s);
  113. ans1 += tr[s].get_ans (s, G._dis[s], G._fa[s], 1);
  114. //存一下最初的have
  115. }
  116. cout << ans1 << " ";
  117. for (int i = 0; i <= G.cnt; i += 2) {
  118. //每次枚举禁用一条边。
  119. LL res_now = 0;
  120. ban[i] = ban[i + 1] = true;//双向都要禁
  121. for (int s = 1; s <= n; ++s) { //枚举删除之后每一棵最短路树的状况
  122. int u = G.e[i].from, v = G.e[i].to, w = G.e[i].w;
  123. if (have[u][v] && w == minw[u][v]) G.dijkstra (s);
  124. res_now += tr[s].get_ans (s, G._dis[s], G._fa[s], 0);
  125. }
  126. ban[i] = ban[i + 1] = false;
  127. ans2 = max (ans2, res_now);
  128. }
  129. cout << ans2 << endl;
  130. }
  131. }

LA4080/UVa1416 Warfare And Logistics 最短路树的更多相关文章

  1. UVA1416 Warfare And Logistics

    UVA1416 Warfare And Logistics 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36232 [ ...

  2. UVA1416/LA4080 Warfare And Logistics

    题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L 现在要求你求出每两点之间的最短距离和 接着要求 求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值(翻译来 ...

  3. 【UVA1416】(LA4080) Warfare And Logistics (单源最短路)

    题目: Sample Input4 6 10001 3 21 4 42 1 32 3 33 4 14 2 2Sample Output28 38 题意: 给出n个节点m条无向边的图,每条边权都为正.令 ...

  4. UVALive 4080 Warfare And Logistics (最短路树)

    很多的边会被删掉,需要排除一些干扰进行优化. 和UVA - 1279 Asteroid Rangers类似,本题最关键的地方在于,对于一个单源的最短路径来说,如果最短路树上的边没有改变的话,那么最短路 ...

  5. la4080 Warfare And Logistics 罗列+最短

    为了图.计算最短随机分ans1.和删除边缘.免费才能够获得最大和短路之间的最大分ans2,如果这两个不沟通.看作是两个点之间的最短距离l. 第一个想法是枚举每个边缘,然后运行n最短时间.但是,这种复杂 ...

  6. 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)

    layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...

  7. Warfare And Logistics UVA - 1416

    题目链接:https://vjudge.net/problem/UVA-1416 题解: 这是一个最短路的好题,首先我们考虑如果暴力弗洛伊德,显然时间复杂度不对,如果做n次spfa好像复杂度也不对,所 ...

  8. hdu 3409 最短路树+树形dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3409 参考博客:http://www.cnblogs.com/woaishizhan/p/318981 ...

  9. BZOJ1975[Sdoi2010]魔法猪学院——可持久化可并堆+最短路树

    题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...

随机推荐

  1. 硬杠后端(后端坑系列)——Django前期工作

    Django是一个开放源代码的Web应用框架,由Python写成,采用了MVC的框架模式. MVC MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件 ...

  2. 微信小程序 canvas导出图片模糊

    //保存到手机相册save:function () { wx.canvasToTempFilePath({ x: , y: , width: , //导出图片的宽 height: , //导出图片的高 ...

  3. 《JavaScript高级程序设计》笔记:面向对象的程序设计(六)

    面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象. 理解对象 创建自定义对象的最简单的方法就是创建一个Object的实例,然后再为它添加属性和方法.例 ...

  4. loj#6041. 「雅礼集训 2017 Day7」事情的相似度(SAM set启发式合并 二维数点)

    题意 题目链接 Sol 只会后缀数组+暴躁莫队套set\(n \sqrt{n} \log n\)但绝对跑不过去. 正解是SAM + set启发式合并 + 二维数点/ SAM + LCT 但是我只会第一 ...

  5. 四款让你绝对上瘾的手机APP 用一次就会爱不释手

    如今我们出门在外,无时无刻不都在使用手机,在外游玩吃饭.乘地铁公交.购物逛街等,只要有手机不需要现金就可以完成这些事情,手机功能我们每天都在使用着,不用多说,大家都知道手机的重要性. 下面就是分享福利 ...

  6. jQuery元素操作

    jQuery中创建元素及追加元素 DOM中可以动态创建元素:document.createElement(“标签的名字”); jQuery中同样可以创建元素标签,并且返回的就是jQuery对象,可以直 ...

  7. Java中的Iterable与Iterator详解

    在Java中,我们可以对List集合进行如下几种方式的遍历: List<Integer> list = new ArrayList<>(); list.add(5); list ...

  8. SQLsever 复制一行内容到本表

    insert into Table (userName,userAge) select userName,userAge from Table where Id=66 这里并不是 insert int ...

  9. OpenGL实例:几何变换

    OpenGL实例:几何变换 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 更多请查看:计算机图形学 1. 平移 #include <GL/glu ...

  10. ngxin 配置ssl

    1.上aliyun.com 申请免费ssl证书, 登录aliyun后搜索 “ca证书” , 申请使用“文件验证”,把文件传到服务器指定目录上,验证即可. 2.然后下载证书, 解压后传到服务器上, 在n ...