源自大白书

题意 有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. Gnome排序

    Gnome排序(地精排序),起初由Hamid Sarbazi-Azad 于2000年提出,并被称为stupid排序,后来被Dick Grune描述并命名为“地精排序”,作为一个排序算法,和插入排序类似 ...

  2. 【BZOJ5094】硬盘检测 概率

    [BZOJ5094]硬盘检测 Description 很久很久以前,小Q买了一个大小为n单元的硬盘,并往里随机写入了n个32位无符号整数.因为时间过去太久,硬盘上的容量字眼早已模糊不清,小Q也早已忘记 ...

  3. git如何回滚当前修改的内容?

    git如何回滚当前修改的内容? 1.打开git gui,在工具栏上点击 commit ,选择 Revert Changes,  这里可以回滚单个文件: 2.一键回滚所有修改: 打开git gui,在工 ...

  4. python-django开发学习笔记二

    1.简述 1.1 开发环境 该笔记所基于的开发环境为:windows8.python2.7.5.psycopg2-2.4.2.django1.5.4.pyCharm-2.7.3.以上所描述的软件.插件 ...

  5. Spring Framework框架容器核心源码逐步剖析

    目录 构建Spring环境 Spring 版本 5.1.3.RELEASE 测试类 Spring 配置文件 测试方法Main 快速进入Debug查看IOC容器构建源码 Spring IOC源码步骤分析 ...

  6. Oracle体系结构之OFM管理

    OMF:oracle management files 作用:不用指定文件的路径大小名字 OMF管理数据文件:db_create_file_dest 传统方式:SQL>create tables ...

  7. $w=$mysqli->query($sql);

    $db = new mysqli('localhost', 'root', '', 'w'); if($db->connect_error){ die('Connect Error ( '.$d ...

  8. IOS--jenkins ,app,reengine

    传统的对iOS逆向的工具要使用到下面很多: clutchotoolkeychain-dumpersqlitedumpdecryptedclass-dump-zTheos http://iosapp.m ...

  9. Qt中容器类应该如何存储对象(对象加入到容器时会发生拷贝,容器析构时,容器内的对象也会析构)

    Qt提供了丰富的容器类型,如:QList.QVector.QMap等等.详细的使用方法可以参考官方文档,网上也有很多示例文章,不过大部分文章的举例都是使用基础类型:如int.QString等.如果我们 ...

  10. ChinaTest测试感悟

    这次去北京参加ChinaTest大会,听了各位大师和同行的心得和感悟,收获颇多.很喜欢这样的大会,可以听到测试的各种声音各种观点.当没有对错时,需要思考的就是怎样采取最适合当前环境的策略.言归正传,谈 ...