源自大白书

题意 有n座城市通过m条双向道路相连,每条道路都有一个危险系数。你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有的边的大最大危险系数最小。

解: 首先求出最小生成树,并把它改写成有根树,让fa[i]和cost[i]分别表示节点i的父亲编号和它与父亲之间的边权,L[i]表示节点i的深度,接下来通过预处理计算出数组anc 和 maxcost 其中anc[i][j] 表示节点i的2^j 级祖先的编号 macost[i][j] 表示i到2^j级 祖先之间的最大权值。

有了预处理 私用LCA 来查询结果, 查询p,q, 并且p比q深, 则可以先把p提升到和q处于同一级的位置,然后用二进制展开的方法不断把p和q同时往上提(保证二者深度相等),同时更新最大的边权

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
const int maxn = +;
const int INF =;
struct Edge{
int from,to, dist;
bool operator <(const Edge & rhs)const{
return dist<rhs.dist;
}
}E[maxn*];
struct ed{
int to,dist;
};
vector<ed> G[maxn];
int fa[maxn],per[maxn],cost[maxn],L[maxn];
int anc[maxn][],maxcost[maxn][];
void inti(int n){
for(int i =; i<n; i++){
per[i] = i;
G[i].clear();
}
}
void preprocess( int n){
for(int i=; i<n ; i++){
anc[i][] = fa[i]; maxcost[i][]=cost[i];
for(int j=; (<<j)<n; j++) anc[i][j]=-;
}
for(int j =; (<<j)<n; j++)
for(int i=; i<n; i++){
if(anc[i][j-]!=-){
int a = anc[i][j-];
anc[i][j]=anc[a][j-];
maxcost[i][j] = max(maxcost[i][j-],maxcost[a][j-]);
}
}
}
int fid(int u){
return per[u]==u?u:(per[u]= fid(per[u]));
}
void dfs(int u, int p,int dist, int depth){
fa[u]=p; cost[u] = dist; L[u] = depth;
for(int i = ; i<(int)G[u].size(); ++i){
ed e = G[u][i];
if(e.to == p) continue;
dfs(e.to,u,e.dist,depth+);
}
}
int query(int p, int q){
int log;
if(L[p]<L[q]) swap(p,q);
for( log =; (<<log)<=L[p]; log++); log--;
int ans=-INF;
for(int i = log ; i>=; i--)
if( L[p] - (<<i) >= L[q] ){
ans = max(ans,maxcost[p][i]);
p = anc[p][i];
}
if(p==q) return ans;
for(int i=log; i>=; i--)
if(anc[p][i]!=- && anc[p][i]!=anc[q][i]){
ans = max(ans,maxcost[p][i]); p = anc[p][i];
ans = max(ans,maxcost[q][i]); q = anc[q][i];
}
ans = max(ans,cost[p]);
ans = max(ans,cost[q]);
return ans;
}
int main()
{
int n,m,f=;
while(scanf("%d%d",&n,&m)==){
inti(n);
for(int i=; i<m ; i++){
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
x--,y--;
E[i]=(Edge){x,y,d};
}
int lest = n;
sort(E,E+m);
for(int i=; i<m; i++){
int a = E[i].from,b=E[i].to, dist= E[i].dist;
int ca = fid(a),cb = fid(b);
if(ca!=cb){
per[ca] =cb;
lest--;
G[a].push_back((ed){b,dist} );
G[b].push_back((ed){a,dist} );
if(lest==) break;
}
}
dfs(,-,,);
preprocess(n);
int Q;
if(f)
puts("");
else f=;
scanf("%d",&Q);
for(int i =; i<Q; i++){
int s,t;
scanf("%d%d",&s,&t);
s--;t--;
printf("%d\n",query(s,t));
} } return ;
}

uva11354 LCA+最小生成树+dp的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. hdu 4081 Qin Shi Huang's National Road System(最小生成树+dp)2011 Asia Beijing Regional Contest

    同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游 ...

  3. POJ3728 LCA RMQ DP

    题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...

  4. POJ3417 LCA+树dp

    http://poj.org/problem?id=3417 题意:先给出一棵无根树,然后下面再给出m条边,把这m条边连上,然后每次你能毁掉两条边,规定一条是树边,一条是新边,问有多少种方案能使树断裂 ...

  5. BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增

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

  6. LCA&最小生成树

    LCA 经常被用来使用.比如询问树两点之间的距离. 比如树上差分 都是经常被使用的类型.有的时候倍增求LCA的同时还可以优化算法. 这道题呢 求一个严格的最小生成树,当然如果不严格的话如果有重边那么就 ...

  7. Codeforces Round #343 (Div. 2) E. Famil Door and Roads lca 树形dp

    E. Famil Door and Roads 题目连接: http://www.codeforces.com/contest/629/problem/E Description Famil Door ...

  8. POJ3728 THE MERCHANT LCA RMQ DP

    题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...

  9. The Shortest Statement(Educational Codeforces Round 51 (Rated for Div.2)+最短路+LCA+最小生成树)

    题目链接 传送门 题面 题意 给你一张有\(n\)个点\(m\)条边的联通图(其中\(m\leq n+20)\),\(q\)次查询,每次询问\(u\)与\(v\)之间的最短路. 思路 由于边数最多只比 ...

随机推荐

  1. 如何分离p12(或pfx)文件中的证书和私钥

    p12(或者pfx)文件里一般存放有CA的根证书,用户证书和用户的私钥 假设我们有一个test.p12文件 在安装了openssl的linux服务器上执行以下命令: 提取用户证书: openssl p ...

  2. 单例模式全面学习(C++版)

    单例模式:用来创建独一无二的,只能够有一个实例的对象. 单例模式的结构是设计模式中最简单的,但是想要完全实现一个线程安全的单例模式还是有很多陷阱的,所以面试的时候属于一个常见的考点~ 单例模式的应用场 ...

  3. 在 arc里面打印 引用计数的方法

    查阅资料:   You can use CFGetRetainCount with Objective-C objects, even under ARC: NSLog(@"Retain c ...

  4. vue之创建组建

    vue的核心基础就是组件的使用,玩好了组件才能将前面学的基础更好的运用起来.组件的使用更使我们的项目解耦合.更加符合vue的设计思想MVVM. 那接下来就跟我看一下如何在一个Vue实例中使用组件吧! ...

  5. bootstrap中点击左边展开

    <div id="sideNav" href=""><i class="material-icons dp48 glyphicon- ...

  6. SQL Fundamentals || DCL(Data Control Language) || 系统权限&对象权限管理(GRANT&REVOKE)

    SQL Fundamentals || Oracle SQL语言 语句 解释 Create user Creates a user(usually performed by a DBA) Grant ...

  7. LAMP下安装zabbix流水

    一.安装zabbix (1)创建用户和组 [root@dbking zabbix-2.2.1]# groupadd zabbix [root@dbking zabbix-2.2.1]# useradd ...

  8. HDFS Users Guide

    Purpose This document is a starting point for users working with Hadoop Distributed File System (HDF ...

  9. linux系统下top命令参数详解

    简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...

  10. LightOJ 1027 - A Dangerous Maze(求期望)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1027 题意:又一个迷宫,有n个门,每个门又一个值num,如果num>0 说明在n ...