看到第一篇题解的神奇码风……我决定发一篇码风正常的题解造福人类

这题的做法也非常经典,最大生成树\(+LCA\),相当于先贪心一下,在LCA的时候记录一下当前最小的边权

顺便吐槽一下最后一个测试点:

testdata.in
7 8
1 2 2
1 3 5
3 4 4
4 4 2
3 5 3
6 7 4
1 3 3
4 5 8
8
1 2
1 4
1 3
1 5
1 6
2 5
3 5
6 7
testdata.out
2
4
5
4
-1
2
4
4

回到题面:注意: \(x\)不等于\(y\),两座城市之间可能有多条道路

虽然\(Kruskal\)不会挂掉……但是出题人造数据真不严谨

\(Code\ Below:\)

#include <bits/stdc++.h>
#define INF 99999999
using namespace std;
const int maxn=10000+10;
const int maxm=50000+10;
int n,m,q,head[maxn],f[maxn],tot;
//如题目所示,存储链式前向星和并查集
int fa[maxn][16],w[maxn][16],dep[maxn],rt,t;
//fa[i][j]表示第i个结点向上跳2^i个结点,dep[i]存储第i个结点的深度
struct Edge{
int x,y,w;
}e[maxm];
struct node{
int to,next,val;
}tree[maxm<<1];
inline bool cmp(Edge a,Edge b){//cmp
return a.w>b.w;
}
inline int read(){//读入优化
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void swap(int &a,int &b){int t=a;a=b;b=t;}//交换
inline void add(int x,int y,int w){//存边
tree[++tot].to=y;
tree[tot].val=w;
tree[tot].next=head[x];
head[x]=tot;
}
int find(int x){//并查集
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
inline void Kruskal(){//最大生成树
for(int i=1;i<=n;i++)
f[i]=i;
sort(e+1,e+m+1,cmp);
int ans=0;
for(int i=1;i<=m;i++){
int a=find(e[i].x),b=find(e[i].y);
if(a!=b){
f[a]=b;ans++;
add(e[i].x,e[i].y,e[i].w);
add(e[i].y,e[i].x,e[i].w);
}
}
}
void dfs(int x,int pre,int val){//LCA预处理
dep[x]=dep[pre]+1;
w[x][0]=val;
fa[x][0]=pre;
for(int i=1;i<=t;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
w[x][i]=min(w[x][i-1],w[fa[x][i-1]][i-1]);
}
for(int i=head[x];i;i=tree[i].next){
if(tree[i].to!=pre){
dfs(tree[i].to,x,tree[i].val);
}
}
}
inline int LCA(int x,int y){//倍增LCA
if(dep[x]<dep[y]) swap(x,y);
int ans=INF;
for(int i=t;i>=0;i--)
if(dep[fa[x][i]]>=dep[y]){
ans=min(ans,w[x][i]);
x=fa[x][i];
}
if(x==y) return ans;
for(int i=t;i>=0;i--)
if(fa[x][i]!=fa[y][i]){
ans=min(ans,min(w[x][i],w[y][i]));
x=fa[x][i],y=fa[y][i];
}
int val=w[x][0];
if(fa[x][0]!=y) val=min(val,w[y][0]);
return min(ans,val);
} int main()
{
memset(fa,INF,sizeof(fa));
memset(w,INF,sizeof(w));
n=read(),m=read();t=log2(n)+1;
for(int i=1;i<=m;i++){
e[i].x=read(),e[i].y=read(),e[i].w=read();
}
Kruskal();
//记住!数据不一定联通!图是一个森林!
for(int i=1;i<=n;i++)
if(i==f[i])
dfs(i,i,INF);
scanf("%d",&q);
while(q--){
int x=read(),y=read();
//printf("%d %d\n",find(x),find(y));
if(find(x)!=find(y)) printf("-1\n");
else printf("%d\n",LCA(x,y));
}
return 0;
}

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

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

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

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

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

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

    题目大意:给你一张n个点m条边的图,有q次询问,每次让你找出一条从x至y的路径,使得路径上经过的边的最小值最大,输出这个最大的最小值. 显然,经过的路径必然在这张图的最大生成树上. 我们求出这个图的最 ...

  4. 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

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

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

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

  6. 货车运输 noip2013 luogu P1967 (最大生成树+倍增LCA)

    luogu题目传送门! 首先,题目让我们求每个货车的最大运输量,翻译一下就是求路径上边权最小的边. 利用一下贪心思想可知,所有货车肯定都会尽量往大的边走. 进一步翻译,即为有一些小边货车根本不会走,或 ...

  7. NOIP2013D1T3货车运输(最大生成树+倍增lca)

    传送门 这道题,先用kruskal求一遍图中的最大生成树. 然后,倍增求lca,求lca的同时求出边权的最小值. #include <cstring> #include <cstdi ...

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

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

  9. Luogu1967 NOIP2013 货车运输 最大生成树、倍增

    传送门 题意:给出一个$N$个节点.$M$条边的图,$Q$次询问,每一次询问两个点之间的所有可行路径中经过的边的边权的最小值中的最大值.$N \leq 10000 , M \leq 50000 , Q ...

随机推荐

  1. HTML and CSS学习概述

    一·Web浏览器是一个连接到Web服务器,向Web服务器请求信息,然后解析返回来的HTML标记,并将其显示在浏览器窗口内的程序.1.Microsoft 2.Internet Explorer(IE)3 ...

  2. 再读c++primer plus 004

    第九章  内存模型和名称空间 1.如果文件名包含在尖括号中,则c++编译器将在存储标准头文件的主机系统的文件系统中查找,但如果文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录(或其他 ...

  3. 62.Xcode 添加代码块

    1. Xcode创建一个新项目,打开一个.h或者.m文件 2.我举例以设置属性为例 #import <UIKit/UIKit.h> @interface ViewController : ...

  4. 01.Java 开发简单的计算器

    难度为一般,适合具有 Java 基础和 Swing 组件编程知识的用户学习一. 实验介绍1.1 实验内容本次实验利用Java开发一个可以进行简单的四则运算的图形化计算器,会使用到 Java Swing ...

  5. org.jsoup.HttpStatusException: HTTP error fetching URL. Status=403

    爬取网站的时候 conn = Jsoup.connect(url).timeout(5000).get();直接用get方法,有些网站可以正常爬取. 但是有些网站报403错误,403是一种在网站访问的 ...

  6. 2018.11.09 bzoj4773: 负环(倍增+floyd)

    传送门 跟上一道题差不多. 考虑如果环上点的个数跟最短路长度有单调性那么可以直接上倍增+floyd. 然而并没有什么单调性. 于是我们最开始给每个点初始化一个长度为0的自环,于是就有单调性了. 代码: ...

  7. 使用promise判断是否登录

    步骤: 1.创建并返回new Promise((success,error)=>{}),success和error分别是成功和失败后所执行的函数 2.判断是否含有cookie,如果含有cooki ...

  8. Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)

    https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...

  9. java Concurrent包学习笔记(一):ExecutorService

    一.介绍 ExecutorService是java.util.concurrent包中的一个线程池实现接口.其有两个实现类: 1)ThreadPoolExecutor:普通线程池通过配置线程池大小,能 ...

  10. linux下的wireshark最新版安装(源码安装)以及一些常见问题

    源码安装教程 http://www.cnblogs.com/littleTing/p/3765589.html 1.下载wireshark: 网址:http://www.wireshark.org/d ...