题意:N个点,M条路,每条路的危险度为路上各段中最大的危险度。多组询问,点s到点t的所有路径中最小的危险度。

分析:

1、首先建个最小生成树,则s到t的路径一定是危险度最小的。

原因:建最小生成树的最后一步,如果有两个相等的边可以选择,然后将两个连通块连在一起。

那不管选择哪个边,对于分别位于两个连通块的两点来说,这条边都是必经之路,而这个必经之路是这两点路径的危险度中最大的,起决定作用,所以选哪个是一样的。

2、利用lca,在找s和t最近公共祖先的过程中,不断取两者路径中的最大危险度即可。

3、d[k][v] 为点v到它向上走2k步所到的顶点的路径中最大的危险度。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 50000 + 10;
const int MAXT = 100000 + 10;
using namespace std;
struct Node{
int a, b;
Node(int aa, int bb):a(aa), b(bb){}
};
int N, M;
int fa[MAXN];
int d[20][MAXN];
int depth[MAXN];
int parent[20][MAXN];
vector<Node> G[MAXN];
int Find(int x){
return fa[x] = (fa[x] == x) ? x : Find(fa[x]);
}
struct Edge{
int x, y, d;
void read(){
scanf("%d%d%d", &x, &y, &d);
}
bool operator < (const Edge& rhs)const{
return d < rhs.d;
}
}num[MAXT];
void kruskal(){
for(int i = 0; i < M; ++i){
int tmpx = Find(num[i].x);
int tmpy = Find(num[i].y);
if(tmpx == tmpy) continue;
G[num[i].x].push_back(Node(num[i].y, num[i].d));
G[num[i].y].push_back(Node(num[i].x, num[i].d));
if(tmpx < tmpy) fa[tmpy] = tmpx;
else fa[tmpx] = tmpy;
}
}
void dfs(int v, int fa, int deep){
parent[0][v] = fa;
depth[v] = deep;
int len = G[v].size();
for(int i = 0; i < len; ++i){
if(G[v][i].a != fa){
d[0][G[v][i].a] = G[v][i].b;
dfs(G[v][i].a, v, deep + 1);
}
}
}
void LCA_init(){
dfs(1, -1, 0);
for(int k = 0; k + 1 < 20; ++k){
for(int v = 1; v <= N; ++v){
if(parent[k][v] < 0) parent[k + 1][v] = -1;
else{
parent[k + 1][v] = parent[k][parent[k][v]];
d[k + 1][v] = max(d[k][v], d[k][parent[k][v]]);
}
}
}
}
int lca(int u, int v){
int ans = 0;
if(depth[u] > depth[v]) swap(u, v);
for(int k = 0; k < 20; ++k){
if(((depth[v] - depth[u]) >> k) & 1){
ans = max(ans, d[k][v]);
v = parent[k][v];
}
}
if(u == v) return ans;
for(int k = 19; k >= 0; --k){
if(parent[k][u] != parent[k][v]){
ans = max(ans, d[k][u]);
ans = max(ans, d[k][v]);
u = parent[k][u];
v = parent[k][v];
}
}
ans = max(ans, d[0][u]);
ans = max(ans, d[0][v]);
return ans;
}
int main(){
bool flag = true;
while(scanf("%d%d", &N, &M) == 2){
memset(parent, -1, sizeof parent);
memset(d, 0, sizeof d);
memset(depth, 0, sizeof depth);
for(int i = 1; i < MAXN; ++i){
fa[i] = i;
G[i].clear();
}
for(int i = 0; i < M; ++i){
num[i].read();
}
sort(num, num + M);
kruskal();
LCA_init();
int Q;
scanf("%d", &Q);
if(flag) flag = false;
else printf("\n");
while(Q--){
int s, t;
scanf("%d%d", &s, &t);
printf("%d\n", lca(s, t));
}
}
return 0;
}

  

UVA - 11354 Bond(最小生成树+LCA+瓶颈路)的更多相关文章

  1. UVA 11354 Bond(最小瓶颈路+倍增)

    题意:问图上任意两点(u,v)之间的路径上,所经过的最大边权最小为多少? 求最小瓶颈路,既是求最小生成树.因为要处理多组询问,所以需要用倍增加速. 先处理出最小生成树,prim的时间复杂度为O(n*n ...

  2. UVA 11354 Bond 最小生成树 + lca

    题意 给出一张图,q个询问,每次询问给出uv,找出一条路径,使这条路径上的最大边权是两点所有路径中最小,输出这个值 思路 很显然要先求出最小生成树,任意两点在最小生成树上有唯一路径,并且这条路径上的最 ...

  3. UVA 11354 - Bond (最小生成树 + 树链剖分)

    题目链接~~> 做题感悟:这题開始看到时感觉不是树不优点理,一想能够用 Kruskal 处理成树 ,然后就好攻克了. 解题思路: 先用 Kruskal 处理出最小生成树.然后用树链剖分 + 线段 ...

  4. 训练指南 UVA - 11354(最小生成树 + 倍增LCA)

    layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...

  5. uva 11354 - Bond(树链拆分)

    题目链接:uva 11354 - Bond 题目大意:给定一张图.每次询问两个节点路径上进过边的危急值的最大值的最小值. 解题思路:首先建立最小生成数,然后依据这棵树做树链剖分. #include & ...

  6. UVA 11354 Bond 邦德 (RMQ,最小瓶颈MST)

    题意: n个城市,m条路,每条路有个危险值,要使得从s走到t的危险值最小.回答q个询问,每个询问有s和t,要求输出从s到t最小的危险值.(5万个点,10万条边) 思路: 其实要求的是任意点对之间的最小 ...

  7. UVA 11354 Bond(MST + LCA)

    n<=50000, m<=100000的无向图,对于Q<=50000个询问,每次求q->p的瓶颈路. 其实求瓶颈路数组maxcost[u][v]有用邻接矩阵prim的方法.但是 ...

  8. Codeforces 632F - Magic Matrix(暴力 bitset or Prim 求最小生成树+最小瓶颈路)

    题面传送门 开始挖老祖宗(ycx)留下来的东西.jpg 本来想水一道紫题作为 AC 的第 500 道紫题的,结果发现点开了道神题. 首先先讲一个我想出来的暴力做法.条件一和条件二直接扫一遍判断掉.先将 ...

  9. uva 11354 Bond

    题意: 邦德在逃命!他在一个有N个城市,由M条边连接的道路网中.一条路的危险度被定义为这条路上危险度最大的边的危险度. 现在给出若干个询问,s,t,问从s到t的最小的危险度是多少. 思路: 首先可以证 ...

随机推荐

  1. linux kill命令以及 信号

    kill命令介绍 命令作用 终止一个进程 语法: kill [-s signal|-p] [-q sigval] [-a] [--] pid... kill -l [signal] 选项 -l 信号, ...

  2. 「luogu1613」跑路

    传送门 Luogu 解题思路 对于所有可以用 \(2^k\) 形式表示的 \(dis(i,j)\),将\(i,j\)之间的 \(dis\) 置为 \(1\),可以用倍增 \(\text{Floyd}\ ...

  3. ASP.NET MVC Web项目中使用Log4Net记录日志,并按照日志类型分文件存储

    1.创建MvcLog4Net项目 2.创建 空的MVC项目 3.项目创建完成的效果 4.选择项目,点击鼠标右键,在弹出菜单中选择“管理解决方案的 NuGet 程序包” 5. 在NuGet浏览界面: 点 ...

  4. 为常用的块类型创建typedef

    本文概要: 1.块类型的语法结构 2.使用C语言中的“类型定义”的特性.使用typedef关键字用于给块类型起个别名 3.使用typedef好处之一是,重构块的类型签名时只需要改一处就行了,避免遗留b ...

  5. Python字符串(二)

    四.类型转换 1. 基本语法: 类型名(数据) --- 将指定数据转换成指定类型 说明:类型名 -任何python支持的,或者自定的类型都可以数据 -需要转换的对象,类型不同要求可能不一样 2. 转换 ...

  6. Linux centosVMware shell脚本介绍、shell脚本结构和执行、date命令用法、shell脚本中的变量

    一. shell脚本介绍 shell是一种脚本语言 aming_linux blog.lishiming.net 可以使用逻辑判断.循环等语法 可以自定义函数 shell是系统命令的集合 shell脚 ...

  7. [经验] Cocos Creator使用笔记 --- 调用不同脚本下的函数

    因为 JavaScript 不同于 Java, 想要调用不同文件的函数的话不能直接 ClassName object = new ClassName(); object.function(param) ...

  8. JavaSwing标准对话框

    package test001; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import jav ...

  9. CH8 课后习题

    8.1和8.2 #include <iostream> using namespace std; istream& f(istream& in) { int v; in & ...

  10. Redis列表类型

    列表类型(list) 可以存储一个有序的字符串列表.常用的操作是向列表两端添加元素. 一个列表类型键最多能容纳2^32 -1个元素. 命令 向列表两端增加元素 LPUSH key value [val ...