题意:给出一颗n个点的图,q个询问,每次询问u到v的路径中最小的边最大是多少。

图的最大生成树有一个性质,对于该图的任意两个点,在树中他们之间路径的最小边最大。

由于这个图不一定联通,于是我们对它的联通块都求一次最大生成树。

每次询问就变成了在最大生成树上找出u到v路径的最小边。

这个显然可以用LCA维护点到它的2^x祖先之间的边的最小值来解决。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... const int DEG=;
struct Edge{int p, next, w;}edge[N<<];
struct Node{int u, v, w;}node[N*];
int head[N], cnt=, F[N], from[N];
int fa[N][DEG], mi[N][DEG], deg[N];
queue<int>que; void add_edge(int u, int v, int w){edge[cnt].p=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;}
bool comp(Node a, Node b){return a.w>b.w;}
int find(int x){return F[x]==-?x:F[x]=find(F[x]);}
void Kruscal(int n){
mem(F,-); sort(node+,node+*n+,comp);
FOR(i,,*n) {
int u=node[i].u, v=node[i].v, t1=find(u), t2=find(v);
if (t1!=t2) add_edge(u,v,node[i].w), add_edge(v,u,node[i].w), F[t1]=t2;
}
}
void BFS(int root){
deg[root]=; fa[root][]=root; mi[root][]=INF; que.push(root);
while (!que.empty()) {
int tmp=que.front(); que.pop();
FO(i,,DEG) fa[tmp][i]=fa[fa[tmp][i-]][i-], mi[tmp][i]=min(mi[tmp][i-],mi[fa[tmp][i-]][i-]);
for (int i=head[tmp]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fa[tmp][]) continue;
deg[v]=deg[tmp]+; fa[v][]=tmp; mi[v][]=edge[i].w; que.push(v);
}
}
}
int LCA(int u, int v){
int ans=INF;
if (deg[u]>deg[v]) swap(u,v);
int hu=deg[u], hv=deg[v], tu=u, tv=v;
for (int det=hv-hu, i=; det; det>>=, ++i) if (det&) ans=min(ans,mi[tv][i]), tv=fa[tv][i];
if (tu==tv) return ans;
for (int i=DEG-; i>=; --i) {
if (fa[tu][i]==fa[tv][i]) continue;
ans=min(ans,mi[tu][i]); ans=min(ans,mi[tv][i]);
tu=fa[tu][i]; tv=fa[tv][i];
}
return min(ans,min(mi[tu][],mi[tv][]));
}
int main ()
{
int n, m, q, u, v;
scanf("%d%d",&n,&m);
FOR(i,,m) scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);
Kruscal(m);
int pos=;
FOR(i,,n) {
int v=find(i);
if (from[v]==) from[v]=, BFS(v);
}
scanf("%d",&q);
while (q--) {
scanf("%d%d",&u,&v);
if (find(u)!=find(v)) {puts("-1"); continue;}
printf("%d\n",LCA(u,v));
}
return ;
}

luogu 1967 货车运输(最大生成树+LCA)的更多相关文章

  1. [luogu 1967]货车运输

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

  2. kruskal - 倍增 - 并查集 - Luogu 1967 货车运输

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

  3. 【NOIP2013】货车运输 最大生成树+LCA

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

  4. LUOGU P1967 货车运输(最大生成树+树剖+线段树)

    传送门 解题思路 货车所走的路径一定是最大生成树上的路径,所以先跑一个最大生成树,之后就是求一条路径上的最小值,用树剖+线段树,注意图可能不连通.将边权下放到点权上,但x,y路径上的lca的答案不能算 ...

  5. Luogu P1967 货车运输(Kruskal重构树)

    P1967 货车运输 题面 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \ ...

  6. codevs3287货车运输(最小生成树+LCA)

    3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description A 国有 ...

  7. P1967 货车运输(倍增LCA,生成树)

    题目链接: https://www.luogu.org/problemnew/show/P1967 题目描述 A国有n座城市,编号从 1到n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制, ...

  8. TZOJ 4848 货车运输(最大生成树+倍增lca)

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

  9. $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

    $Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...

随机推荐

  1. SupperSocket深入浅出(二)

    如果还没有看SuperStock深入浅出(一) ,请先看 这一章,主要说下命令是如果运行的.刚开始的时候会发现拷别人的代码命令是可以运行的,在修改的过程中突然发现命令无效了? 这里什么原因?,我先把代 ...

  2. 二、Web框架实现

    一.简单web(socket) 在前一篇WEB框架概述一文中已经详细了解了:从浏览器键入一个URL到返回HTML内容的整个过程.说到底,本质上其实就是一个socket服务端,用户的浏览器其实就是一个s ...

  3. Redash二次开发-开发环境搭建

    环境:win7+pycharm 2018.2 +redash 1.安装pycharm并如何正常使用,找度娘. 2.配置pycharm vcs,设置github用户,从github新建redash项目 ...

  4. nuget必备插件(待续)

    DevLib.ExtensionMethods Extend Z.ExtensionMethods

  5. mnist手写数字识别(神经网络)

    import numpy as np from sklearn.neural_network import MLPClassifier path = 'mnist.npz' f = np.load(p ...

  6. Raft 一致性协议算法 《In search of an Understandable Consensus Algorithm (Extended Version)》

    <In search of an Understandable Consensus Algorithm (Extended Version)>   Raft是一种用于管理日志复制的一致性算 ...

  7. 【转载】IntelliJ IDEA 2017常用快捷键

    IntelliJ IDEA 是一款致力于提供给开发工程师沉浸式编程体验的IDE工具,所以在其中提供了很多方便高效的快捷键,一旦熟练掌握,整个开发的效率和体验将大大提升.本文就按照笔者自己日常开发时的使 ...

  8. 二叉树的深度<java版>

    二叉树的结构 二叉树是比较常见的一种的一种数据结构. 首先看看二叉树的数据结构: //由左节点和右节点以及一个节点值构成 public class TreeNode{ TreeNode leftNod ...

  9. 423. Valid Parentheses【LintCode java】

    Description Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine ...

  10. 城市规模越大,工资、GDP、犯罪率越高:4.5星|《规模》

    规模 信息浓度非常高的一本书.篇幅也不小,纸书有568页,致谢与注释只占7%. 全书讲各种复杂的东西中存在的普遍规律:哺乳动物体重每增加一倍,心率降低25%:城市人口每增加一倍,加油站只增加85%:城 ...