题解 【luoguP1967 NOIp提高组2013 货车运输】
题解
题意
- 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大
 
算法:Kruskal最大生成树+倍增lca
分析
- 首先容易知道,答案一定在该图的最大生成树上
 - 之后问题便转换成了树上点\(u\)到\(v\)的简单路径42中最小的边权
 - 经典的树上倍增
 - 用fa[i][j]来表示从第\(i\)个点往上\(2^j\)条边到达的点
 - 用s[i][j]来表示从第\(i\)个点往上\(2^j\)条边中的最小值
 - 答案就是在求lca的过程中统计一下最小值就可以了(具体详见代码)
 
复杂度:
Kruskal \(O(m \log m)\)
倍增 \(O(n \log n)\)
总复杂度 \(O(n \log n + m \log m)\)
代码:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 50050;
int n, m, q;
int p[MAXN];
int dep[MAXN], vis[MAXN], fa[MAXN][20], s[MAXN][20];
struct Edge
{
	int u, v, w;
	bool operator < (const Edge &_edge) const
	{
		return w > _edge.w;
	}
}edge[MAXN];
int ecnt;
struct node
{
	int v, w;
	node *next;
}pool[MAXN], *head[MAXN];
void addedge(int u, int v, int w)
{
	node *p = &pool[++ecnt], *q = &pool[++ecnt];
	p->v = v, p->w = w, p->next = head[u], head[u] = p;
	q->v = u, q->w = w, q->next = head[v], head[v] = q;
}
int find(int x)
{
	if(p[x] == 0) return x;
	else return p[x] = find(p[x]);
}
bool Union(int x, int y)
{
	int px = find(x);
	int py = find(y);
	if(px == py)
		return false;
	p[px] = py;
	return true;
}
void dfs(int u)
{
	int v;
	vis[u] = 1;
	for(node *p = head[u]; p; p = p->next)
	    if(!vis[v = p->v])
	    {
	    	dep[v] = dep[u] + 1;
	    	fa[v][0] = u;
	    	s[v][0] = p->w;
	    	for(int j = 1; fa[v][j - 1] != 0; j++)
	    	    fa[v][j] = fa[fa[v][j - 1]][j - 1],
	    	    s[v][j] = min(s[v][j - 1], s[fa[v][j - 1]][j - 1]);
	    	    //预处理
	    	dfs(v);
		}
}
int query(int u, int v)//倍增
{
	int ret = 2147483647;//返回值。因为求最小,所以初始赋最大
	if(dep[u] < dep[v]) swap(u, v);
	for(int i = 15; i >= 0; i--)
	    if(fa[u][i] != 0 && dep[fa[u][i]] >= dep[v])
	        ret = min(ret, s[u][i]), u = fa[u][i];//一定要先统计最小值
    if(u == v) return ret;
    for(int i = 15; i >= 0; i--)
        if(fa[u][i] != fa[v][i])
            ret = min(ret, min(s[u][i], s[v][i])), //统计最小
            u = fa[u][i],
            v = fa[v][i];
    ret = min(ret, min(s[u][0], s[v][0]));//不要忘了最后还有两条边
    return ret;
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++)
	    scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
	sort(edge + 1, edge + m + 1);
	for(int i = 1; i <= m; i++)
    	if(Union(edge[i].u, edge[i].v))
    	    addedge(edge[i].u, edge[i].v, edge[i].w);
    dfs(1);
    scanf("%d", &q);
    for(int i = 1; i <= q; i++)
    {
    	int u, v;
    	scanf("%d%d", &u, &v);
    	if(find(u) != find(v))
    	{
    		printf("-1\n");
    		continue ;
		}
    	printf("%d\n", query(u, v));
	}
	return 0;
}
												
											题解 【luoguP1967 NOIp提高组2013 货车运输】的更多相关文章
- NOIP提高组 2013货车运输
		
觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...
 - 【NOIP】提高组2013 货车运输
		
[算法]最大生成树+LCA(倍增) [题解]两点间选择一条路径最小值最大的路径,这条路径一定在最大生成树上,因为最大生成树就是从边权最大的边开始加的. 先求原图的最大生成树(森林),重新构图,然后用一 ...
 - 洛谷P1967 [NOIP2013提高组Day1T2]货车运输
		
P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...
 - 【NOIP2013提高组】货车运输
		
货车运输 (truck.cpp/c/pas) [问题描述] A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆 ...
 - 洛谷P1966 火柴排队[NOIP提高组2013]
		
我确信我应该是做过这道题……就当再写一遍好了. 贪心思想,一番证明得出a和b数组中最小对最小,次小对次小……时解最优.那么先处理出a,b之间的对应关系,然后按照该关系求a或者b的逆序对数量就是答案 / ...
 - NOIP提高组2013 D2T3 【华容道】
		
某王 老师给我们考了一场noip2013的真题...心态爆炸! 题目大意: 有一个n*m的棋盘,每个格子上都有一个棋子,有些格子上的棋子能够移动(可移动的棋子是固定的),棋盘中有一个格子是空的,仍何 ...
 - NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
		
NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...
 - NOIP提高组2004 合并果子题解
		
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
 - NOIP提高组历年真题题解
		
2018 铺设道路 差分水题,推一下结论就好了. #include<cstdio> #include<algorithm> using namespace std; ],d[] ...
 
随机推荐
- java实现遍历一个字符串的每一个字母(总结)
			
基础:牢记字符串操作的各种方法:   String s = "aaaljlfeakdsflkjsadjaefdsafhaasdasd"; // 出现次数 int num = ...
 - Ducci序列 (Ducci Sequence,ACM/ICPC Seoul 2009,UVa1594)
			
题目描述: 题目思路: 直接模拟 #include<stdio.h> #include<string.h> #define maxn 105 int less(const ch ...
 - 数据库Mysql的学习(五)-运算符与函数
			
,store,store,store,store FROM bookinfo;//加减乘除取余 //余额大于200 //余额不等于200 SELECT * FROM readerinfo WHERE ...
 - Intro to Probabilistic Model
			
概率论复习 概率(Probability) 频率学派(Frequentist):由大量试验得到的期望频率(致命缺陷:有些事情无法大量试验,例如一封邮件是垃圾邮件的概率,雷达探测的物体是一枚导弹的概率) ...
 - 地牢逃脱(BFS(广度优先搜索))
			
题目描述 给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一 ...
 - ffmpeg实现mjpeg摄像头的采集-预览-拍照
			
摄像头输出是mjpeg格式的,需要实现在线预览功能,然后实现拍照功能 1.可以设置采集图像的分辨率,预览分辨率为640*480,可以自定义 2.ctrl+\ 拍照,ctrl+c 退出 void tes ...
 - Windows下PATH等环境变量详解(转载)
			
本文转载自http://legend2011.blog.51cto.com/3018495/553255 在学习JAVA的过程中,涉及到多个环境变量(environment variable)的概念, ...
 - 2019-1-7Xiaomi Mi5 刷全球版MIUI教程
			
2019-1-7Xiaomi Mi5 刷全球版MIUI教程 mi5 教程 小书匠 欢迎走进zozo的学习之旅. 前言 固件下载 刷机 刷recovery,root 试用体验 其他参考 前言 机器是老 ...
 - iOS-cocoapods使用方法
			
1.CocoaPods的安装及使用: http://code4app.com/article/cocoapods-install-usage http://objccn.io/issue-6-4/ h ...
 - spring ioc经典总结
			
component-scan标签默认情况下自动扫描指定路径下的包(含所有子包),将带有 @Component @Repository @Service @Controller标签的类自动注册到spri ...