题面

Description

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

Input

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

Output

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

Sample Input

4 3

1 2 4

2 3 3

3 1 1

3

1 3

1 4

1 3

Sample Output

3

-1

3

Hint

对于 30%的数据,0 < n <1,000,0 < m < 10,000,0 < q < 1,000;

对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

题解

这道题方法很多很多,听说可以运用网络流、树链剖分等等等方法。

我用的方法适合我这种小蒟蒻

我们看看题目,要求的是给定的两对点之间的所有路径中,路径中最短的边的最大值。

这一类题目很容易想到构造 最大/最小生成树

我们可以证明这条路径必定在最大生成树上。

假设最大生成树上两点之间的路径的最小值为x

若存在另外一条路径,使得这两点之间的路径的最小值为x'

x'>x

那么,根据最小生成树建树的原理,x'这条路径必定会在x之间建出,

因此不可能存在不在最大生成树上的边可以使得答案更大。

那么,求出最大生成树之后,直接使用倍增LCA求解即可

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. using namespace std;
  8. #define MAX 11000
  9. #define MAXL 51000
  10. #define INF 20000000
  11. inline int read()
  12. {
  13. register int x=0,t=1;
  14. register char ch=getchar();
  15. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  16. if(ch=='-'){t=-1;ch=getchar();}
  17. while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
  18. return x*t;
  19. }
  20. int f[MAX],dep[MAX];
  21. int minl[MAX][15],p[MAX][51];
  22. int n,m,Q,u,v,w;
  23. struct Line
  24. {
  25. int u,v,w;//从u到v,权值w
  26. }e[MAXL];
  27. struct Edge
  28. {
  29. int v,next,w;
  30. }E[MAXL];
  31. int h[MAX],cnt=1,tot=1;
  32. inline void Add(int u,int v,int w)//建边
  33. {
  34. E[tot]=(Edge){v,h[u],w};
  35. h[u]=tot++;
  36. }
  37. inline bool operator <(Line a,Line b)//需要求最大生成树
  38. {
  39. return a.w>b.w;
  40. }
  41. int getf(int u)//并查集
  42. {
  43. return f[u]==u?u:f[u]=getf(f[u]);
  44. }
  45. void Build(int u,int ff)//建树
  46. {
  47. for(int i=h[u];i;i=E[i].next)
  48. {
  49. int v=E[i].v;
  50. if(v!=ff)
  51. {
  52. dep[v]=dep[u]+1;
  53. p[v][0]=u;
  54. minl[v][0]=E[i].w;
  55. Build(v,u);
  56. }
  57. }
  58. }
  59. void Prepare()//LCA的预处理
  60. {
  61. for(int j=1;(1<<j)<=n;++j)
  62. {
  63. for(int i=1;i<=n;++i)
  64. {
  65. p[i][j]=p[p[i][j-1]][j-1];
  66. minl[i][j]=min(minl[i][j-1],minl[p[i][j-1]][j-1]);
  67. }
  68. }
  69. }
  70. int Query(int u,int v)//询问
  71. {
  72. int ans=INF;
  73. if(dep[u]<dep[v])swap(u,v);//u是深度大的结点
  74. for(int j=14;j>=0;--j)//使得u,v深度相同
  75. if(p[u][j]&&dep[p[u][j]]>=dep[v])
  76. {
  77. ans=min(ans,minl[u][j]);
  78. u=p[u][j];
  79. }
  80. if(u==v)
  81. return ans;
  82. for(int j=14;j>=0;--j)//找到LCA并求解
  83. {
  84. if(p[u][j]!=p[v][j])
  85. {
  86. ans=min(ans,minl[u][j]);
  87. ans=min(ans,minl[v][j]);
  88. u=p[u][j];
  89. v=p[v][j];
  90. }
  91. }
  92. ans=min(ans,minl[u][0]);
  93. ans=min(ans,minl[v][0]);
  94. return ans;
  95. }
  96. int main()
  97. {
  98. n=read();m=read();
  99. for(int i=1;i<=m;++i)
  100. e[i]=(Line){read(),read(),read()};
  101. sort(&e[1],&e[m+1]);
  102. //克鲁斯卡尔求最大生成树
  103. for(int i=1;i<=n;++i)f[i]=i;//并查集初始化
  104. for(int i=1;i<n;++i)//克鲁斯卡尔
  105. {
  106. while(getf(e[cnt].u)==getf(e[cnt].v)&&cnt<=m)cnt++;//找到下一条可行的边
  107. if(cnt>m)break;//不用连了,没有边了
  108. f[getf(e[cnt].v)]=getf(e[cnt].u);//选择边
  109. Add(e[cnt].u,e[cnt].v,e[cnt].w);
  110. Add(e[cnt].v,e[cnt].u,e[cnt].w);
  111. }
  112. for(int i=1;i<=n;++i)//建树
  113. if(!dep[i])
  114. {
  115. dep[i]=1;
  116. Build(i,0);
  117. }
  118. Prepare();//LCA准备
  119. Q=read();
  120. while(Q--)
  121. {
  122. u=read();v=read();
  123. if(getf(u)!=getf(v))//没有连在一起
  124. printf("-1\n");
  125. else
  126. printf("%d\n",Query(u,v));
  127. }
  128. }

【CJOJ1090】【洛谷1967】【NOIP2013】货车运输的更多相关文章

  1. 【洛谷1967】货车运输(最大生成树+倍增LCA)

    点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...

  2. [Luogu 1967] NOIP2013 货车运输

    [Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...

  3. 【题解】【洛谷 P1967】 货车运输

    目录 洛谷 P1967 货车运输 原题 题解 思路 代码 洛谷 P1967 货车运输 原题 题面请查看洛谷 P1967 货车运输. 题解 思路 根据题面,假设我们有一个普通的图: 作图工具:Graph ...

  4. 【题解】洛谷P1967 [NOIP2013TG] 货车运输(LCA+kruscal重构树)

    洛谷P1967:https://www.luogu.org/problemnew/show/P1967 思路 感觉2013年D1T3并不是非常难 但是蒟蒻还是WA了一次 从题目描述中看出每个点之间有许 ...

  5. [洛谷P1967][题解]货车运输

    题目 这道题让我们求最小限重的最大值 显然可以先求出最大生成树,然后在树上进行操作 因为如果两点之间有多条路径的话一定会走最大的,而其他小的路径是不会被走的 然后考虑求最小权值 可以采用倍增求LCA, ...

  6. NOIP2013 货车运输(最大生成树,倍增)

    NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...

  7. 【洛谷P1967】[NOIP2013]货车运输

    货车运输 题目链接 显然,从一点走到另一点的路径中,最小值最大的路径一定在它的最大生成树上 所以要先求出最大生成树,再在生成树上找最近公共祖先,同时求出最小值. #include<iostrea ...

  8. 洛谷P1967 [NOIP2013提高组Day1T2]货车运输

    P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...

  9. NOIp2013 货车运输 By cellur925

    题目传送门 A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下 ...

  10. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

随机推荐

  1. 前端js代码优化

    今天给大家分享下js代码优化的相关技巧. 1.使用"+"转换为数值     我们平时开发过程中需要将数字字符串创转为number类型,大多数都会用JavaScript parseI ...

  2. RTLabel 的简单使用

    RTLabel 基于富文本的格式,适用于iOS,类似HTML的标记. RTLabel 基于UILabel类的拓展,能够支持Html标记的富文本显示,它是基于Core Text,因此也支持Core Te ...

  3. 【Unity3D技术文档翻译】第1.7篇 AssetBundles 补丁更新

    上一章:[Unity3D技术文档翻译]第1.6篇 使用 AssetBundle Manager 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced ...

  4. Java多线程推荐使用的停止方法和暂停方法

    判断线程结束和让线程结束 package cn.lonecloud.Thread.study; /** * 用于循环1000次的线程 * @Title: Run1000Thread.java * @P ...

  5. Action里面的自带的字段的含义

  6. 初识Vue——模板语法

    一.插值 1.文本 数据绑定最常见的形式是使用双大括号({{  }}--"Mustache"语法)的文本插值 <div class="mustache"& ...

  7. 老男孩Python全栈开发(92天全)视频教程 自学笔记16

    day16课程内容: 装饰器: def outer(): x=10 def inner(): print(x) return innerouter()() #inner 是局部变量,10闭包:如果在一 ...

  8. Angular:利用内容投射向组件输入ngForOf模板

    现在,我们写一个组件puppiesListCmp,用于显示小狗狗的列表: //puppies-list.component.ts @Component({ selector: 'puppies-lis ...

  9. Android ADB Server启动失败

    启动Android Stdio的时候报如下错误: Unable to create Debug Bridge: Unable to start adb server: error: could not ...

  10. 【Learning】最小点覆盖(二分图匹配) 与Konig定理证明

    (附一道例题) Time Limit: 1000 ms   Memory Limit: 128 MB Description 最小点覆盖是指在二分图中,用最小的点集覆盖所有的边.当然,一个二分图的最小 ...