题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732

Description

给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。 
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

现在有 K个询问 (1 < = K < = 20,000)。 
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

Input

第一行: N, M, K。 
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。 
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

Output

对每个询问,输出最长的边最小值是多少。

Sample Input

6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1

Sample Output

5
5
5
4
4
7
4
5

HINT

1 <= N <= 15,000

1 <= M <= 30,000

1 <= d_j <= 1,000,000,000

1 <= K <= 15,000

题解:

由题目可知,此图为连通图

所有路径最长边的最小值,即为最小生成树下路径的最长边。因为在最小生成树下,所有边都是最优的,所以保证了最小值。那自然在最小生成树的路径下,最长边即为所求的边。

步骤:

1.构造最小生成树(无根树)。

2.将最小生成树构造为有根数,并用倍增LCA求出每个节点到第2^i个祖先的路径上的最长边。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+7;
const int maxn = 3e4+10;
const int DEG = 20; struct node
{
int u, v, w;
bool operator<(const node &x)const {
return w<x.w;
}
}e[maxn]; struct edge
{
int to, w, next;
}edge[maxn*2]; int n, m,k;
int head[maxn], tot;
int fa[maxn][DEG], deg[maxn], ma[maxn][DEG], be[maxn]; int find(int x) { return be[x]==x?x:x=find(be[x]); } void add(int u, int v, int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
} void bfs(int root)
{
queue<int>que;
deg[root] = 0;
ma[root][0] = 0;
fa[root][0] = root;
que.push(root);
while(!que.empty())
{
int tmp = que.front();
que.pop();
for(int i = 1; i<DEG; i++)
fa[tmp][i] = fa[fa[tmp][i-1]][i-1], ma[tmp][i] = max( ma[tmp][i-1], ma[fa[tmp][i-1]][i-1]);
for(int i = head[tmp]; i!=-1; i = edge[i].next)
{
int v = edge[i].to, w = edge[i].w;
if(v==fa[tmp][0]) continue;
deg[v] = deg[tmp]+1;
fa[v][0] = tmp;
ma[v][0] = w;
que.push(v);
}
}
} int LCA(int u, int v)
{
int ans = 0;
if(deg[u]>deg[v]) swap(u,v);
int hu = deg[u], hv = deg[v];
int tu = u, tv = v;
for(int det = hv-hu, i = 0; det; det>>=1, i++)
if(det&1)
ans = max(ans, ma[tv][i]), tv = fa[tv][i]; if(tv==tu) return ans;
for(int i = DEG-1; i>=0; i--)
{
if(fa[tu][i]==fa[tv][i]) continue;
ans = max(ans, max( ma[tu][i], ma[tv][i] ) );
tu = fa[tu][i];
tv = fa[tv][i];
}
return ans = max(ans, max( ma[tu][0], ma[tv][0]) );
} int main()
{
tot = 0;
ms(head, -1);
ms(ma,0);
scanf("%d%d%d",&n,&m,&k);
for(int i = 0; i<m; i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e,e+m);
for(int i = 1; i<=n; i++)
be[i] = i;
for(int i = 0; i<m; i++)
{
int u = find(e[i].u), v = find(e[i].v);
if(u!=v)
{
be[u] = v;
add(e[i].u, e[i].v, e[i].w);
add(e[i].v, e[i].u, e[i].w);
}
} bfs(1);
for(int i = 0; i<k; i++)
{
int u, v;
scanf("%d%d",&u,&v);
printf("%d\n",LCA(u,v));
}
}

BZOJ 3732 Network —— 最小生成树 + 倍增LCA的更多相关文章

  1. BZOJ 3732: Network 最小生成树 倍增

    3732: Network 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 &l ...

  2. BZOJ 3732 Network Kruskal+倍增LCA

    题目大意:给定一个n个点m条边的无向连通图.k次询问两点之间全部路径中最长边的最小值 NOIP2013 货车运输.差点儿就是原题...仅仅只是最小边最大改成了最大边最小.. . 首先看到最大值最小第一 ...

  3. 【bzoj3732】Network 最小生成树+倍增LCA

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  4. 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

    [题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...

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

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

  6. 【bzoj4242】水壶 BFS+最小生成树+倍增LCA

    题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入 ...

  7. bzoj 3732 Network(最短路+倍增 | LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3732 [题意] 给定一个无向图,处理若干询问:uv路径上最长的边最小是多少? [思路一 ...

  8. BFS+最小生成树+倍增+LCA【bzoj】4242 水壶

    [bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...

  9. Kruskal重构树+LCA || BZOJ 3732: Network

    题面:https://www.lydsy.com/JudgeOnline/problem.php?id=3732 题解:Kruskal重构树板子 代码: #include<cstdio> ...

随机推荐

  1. django删除表重建&修改用户密码&base64加密解密字符串&ps aux参数说明&各种Error例子

    1.django的queryset不支持负索引 AssertionError: Negative indexing is not supported. 2.django向前端JavaScript传递列 ...

  2. electron入门教程

    1.atom/electron github: https://github.com/atom/electron 中文文档: https://github.com/atom/electron/tree ...

  3. 【hibernate】Hibernate中save, saveOrUpdate, persist, merge, update 区别

    Hibernate Save hibernate save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原 ...

  4. mysql读写分离的三种实现方式

    1 程序修改mysql操作类可以参考PHP实现的Mysql读写分离,阿权开始的本项目,以php程序解决此需求.优点:直接和数据库通信,简单快捷的读写分离和随机的方式实现的负载均衡,权限独立分配缺点:自 ...

  5. C语言变长数组 struct中char data[0]的用法

    版权声明:本文为博主原创文章,未经博主允许不得转载. 今天在看一段代码时出现了用结构体实现变长数组的写法,一开始因为忘记了这种技术,所以老觉得作者的源码有误,最后经过我深思之后,终于想起以前看过的用s ...

  6. python(15)- 装饰器及装饰器的使用

    装饰器 1.无参数 2.函数有参数 3.函数动态参数 4.装饰器参数 装饰器的应用 下面题目同http://www.cnblogs.com/xuyaping/p/6679305.html,只不过加了装 ...

  7. linux查看进程、端口

    1 查看进程pidps -ef|grep tomcat 2 查看进程占用的端口netstat -ntlp|grep pid 3 查看端口对应的进程号lsof -i:portid

  8. 轻松搞定RabbitMQ(四)——发布/订阅

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48729479 翻译地址:http://www.rabbitmq.com/tutorials ...

  9. hessian实战1

    服务端: 1.新建MAVEN HessianServer 项目 2.新建接口 Basic public interface Basic { String hello(String name); Str ...

  10. java ArrayList倒序

    用Collections.reverse(list)即可.如:List<String> list = Arrays.asList(new String[] {"aa", ...