Uva 11354 LCA 倍增祖先
题目链接:https://vjudge.net/contest/144221#problem/B
题意:找一条从 s 到 t 的路,使得瓶颈路最小。
点的数目是10^4,如果向之前的方案求 maxcost数组,O(n*n)时间是过不了的,这个时候,用到了增倍祖先。
关于倍增祖先:http://m.w2bc.com/article/177601
我要补充的是,倍增祖先的优点,是在于倍增,他写的案例,没有体现出倍增,这里强调一下。有点像二分的思想;
利用倍增祖先初始化maxcost[i][j]数组,maxcost[i][j] 在倍增祖先里面表示的,结点 i 的第2j级祖先之间的瓶颈。
用O(nlogn)初始化,然后,查询是O(logn)。
#include <bits/stdc++.h>
using namespace std; const int maxn = + ;
const int INF = 0x3f3f3f3f;
const int logmaxn = ; int n,m; struct Edge
{
int u,v,d;
bool operator < (const Edge& rhs) const
{
return d < rhs.d;
}
}; Edge e[maxn]; int pa[maxn]; int Find_Set(int x)
{
if(x!=pa[x])
pa[x] = Find_Set(pa[x]);
return pa[x];
} vector<int> G[maxn],C[maxn]; struct LCA
{
int n;
int fa[maxn];
int cost[maxn];
int L[maxn];
int anc[maxn][logmaxn];
int maxcost[maxn][logmaxn]; void preprocess()
{
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 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; //lca 是 p 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;
//LCA 是 fa[p] = fa[q];
} }; LCA solver; void dfs(int u,int fa,int level)
{
solver.L[u] = level;
for(int i=; i<G[u].size(); i++)
{
int v = G[u][i];
if(G[u][i]!=fa)
{
solver.fa[v] = u;
solver.cost[v] = C[u][i];
dfs(G[u][i],u,level+);
}
}
} int main()
{
//freopen("in.txt","r",stdin);
int kase = ;
while(scanf("%d%d",&n,&m)==&&n)
{
for(int i=; i<m; i++)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
u--;
v--;
e[i] = (Edge)
{
u,v,d
};
}
sort(e,e+m); for(int i=; i<n; i++)
{
pa[i] = i;
G[i].clear();
C[i].clear();
} for(int i=; i<m; i++)
{
int u = e[i].u;
int v = e[i].v;
int fx = Find_Set(u);
int fy = Find_Set(v); if(fx!=fy)
{
pa[fx] = fy;
G[u].push_back(v);
C[u].push_back(e[i].d);
G[v].push_back(u);
C[v].push_back(e[i].d);
}
}
solver.n = n;
dfs(,-,);
solver.preprocess();
if(kase++!=)
puts("");
int Q;
scanf("%d",&Q);
while(Q--)
{
int u,v;
scanf("%d%d",&u,&v);
u--;
v--;
printf("%d\n",solver.query(u,v));
} } return ;
}
Uva 11354 LCA 倍增祖先的更多相关文章
- 训练指南 UVA - 11354(最小生成树 + 倍增LCA)
layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...
- 洛谷 3379 最近公共祖先(LCA 倍增)
洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...
- CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)
CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...
- LCA(最近公共祖先)——LCA倍增法
一.前人种树 博客:最近公共祖先 LCA 倍增法 博客:浅谈倍增法求LCA 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 代码: const int MAXN ...
- Bond UVA - 11354(LCA应用题)
Once again, James Bond is on his way to saving the world. Bond's latest mission requires him to trav ...
- LCA倍增算法
LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)
1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...
- 【codevs2370】小机房的树 LCA 倍增
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...
随机推荐
- ubuntu-vnc
Centos 中文gnome: 全新以最小化包安装了64位的CentOS6.3系统,作为本地的Web服务器使用,现记录全过程: 1.先安装X Window yum groupinstall " ...
- h5移动版云胶片系统
h5移动版云胶片系统. 最近开了一个医疗用的云胶片,可以对图片放大.图片缩小,图片移动,图片调窗,图片切换,图片播放,图片变灰等等功能.如下图:
- HTML中head里的内容经浏览器解析后全到body里了
HTML中head里的内容经浏览器解析后全到body里了 修改完代码后,用chrome审查元素,head里的内容都到body中去了 http://bbs.csdn.net/topics/3802586 ...
- [原创]在Framelayout中放置button控件出现的覆盖问题
android Framelayout(帧布局)是很常用的布局,主要用来处理需要多个view叠加显示的情况. 然而在使用中,我发现Framelayout中的Button控件,会挡住所有其他控件,而不论 ...
- 深入理解javascript原型和闭包(1)---一切都是对象
深入理解javascript原型和闭包(1)---一切都是对象 type函数输出的类型,在此列出: function show (x){ console.log(typeof(x));//undefi ...
- 关于C#垃圾回收
1.C#垃圾收集器(GC)原理 在C#中托管的资源是无法由程序员管理的,创建销毁都要通过GC来执行.但垃圾收集器有个特点,它是懒惰的,它并不会在变量出了作用域和生命期后立即回收,而是在它认为适当的时候 ...
- Hessian怎样实现远程调用
1.Spring中除了提供HTTP调用器方式的远程调用,还对第三方的远程调用实现提供了支持,其中提供了对Hessian的支持. Hessian是由Caocho公司发布的一个轻量级的二进制协议远程调用实 ...
- Linux -- objdump二进制文件比较
objdump工具用来显示二进制文件的信息,就是以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息. 常用参数说明 -f 显示文件头信息 -D 反汇编所有section (-d反汇编特定se ...
- Discovering-论文
Discovering Spatio-Temporal Causal Interactions in Traffic Data Streams data:real taxi trajectories ...
- Jquery 定时器 倒计时
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...