LCA的五种解法
标准求法
//O(nlogn)-O(logn)
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
int first[maxn],next[maxn*],to[maxn*],dis[maxn*];
int n,m;
void AddEdge(int a,int b,int c)
{
to[++m]=b;
dis[m]=c;
next[m]=first[a];
first[a]=m;
}
int dep[maxn],fa[maxn],cost[maxn],anc[][maxn];
void dfs(int x)
{
dep[x]=dep[fa[x]]+;
for(int i=first[x];i;i=next[i])
{
if(to[i]!=fa[x])
{
fa[to[i]]=x;
cost[to[i]]=cost[x]+dis[i];
dfs(to[i]);
}
}
}
void preprocess()
{
for(int i=;i<=n;i++) anc[][i]=fa[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i<=n;i++)
if(anc[j-][i])
{
int a=anc[j-][i];
anc[j][i]=anc[j-][a];
}
}
int LCA(int p,int q)
{
if(dep[p]<dep[q]) swap(p,q);
int log=;
for(;(<<log)<=dep[p];log++); log--;
for(int i=log;i>=;i--) if(dep[p]-dep[q]>=(<<i)) p=anc[i][p];
if(p==q) return p;
for(int i=log;i>=;i--)
if(anc[i][p]!=anc[i][q])
{
p=anc[i][p];
q=anc[i][q];
}
return fa[p];
}
int main()
{
int a,b,c,Q;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,c);
}
scanf("%d",&Q);
dfs();
preprocess();
while(Q--)
{
scanf("%d%d",&a,&b);
c=LCA(a,b);
printf("%d %d\n",dep[a]+dep[b]-dep[c]*+,cost[a]+cost[b]-cost[c]*);
}
return ;
}
欧拉序列套区间最小值
//O(nlogn)-O(1)
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=;
int n,e=;
int first[maxn],next[maxn*],dis[maxn*],to[maxn*];
void AddEdge(int a,int b,int c)
{
to[e]=b;
dis[e]=c;
next[e]=first[a];
first[a]=e++;
}
int fa[maxn],dep[maxn],d[maxn],p[maxn],A[maxn*],z=;
void dfs(int x)
{
dep[x]=dep[fa[x]]+;
p[x]=z; A[z++]=x;
for(int i=first[x];i;i=next[i])
{
if(fa[x]!=to[i])
{
d[to[i]]=d[x]+dis[i];
fa[to[i]]=x;
dfs(to[i]);
A[z++]=x;
}
}
}
int mv[][maxn*],len[maxn*];
void RMQ_init(int m)
{
for(int i=;i<=m;i++) mv[][i]=A[i];
for(int j=;(<<j)<=m;j++)
for(int i=;i+(<<j)<=m+;i++)
{
mv[j][i]=mv[j-][i];
if(dep[mv[j-][i]]>dep[mv[j-][i+(<<(j-))]]) mv[j][i]=mv[j-][i+(<<(j-))];
}
for(int i=;i<=m;i++)
while(<<(len[i]+)<=i) len[i]++;
}
int LCA(int a,int b)
{
if(a<b) swap(a,b);
int k=len[a-b+];
return dep[mv[k][b]]<dep[mv[k][a-(<<k)+]]?mv[k][b]:mv[k][a-(<<k)+];
}
int main()
{
int a,b,c,Q;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,c);
}
dfs();
RMQ_init(z-);
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&a,&b);
c=LCA(p[a],p[b]);
printf("%d %d\n",dep[a]+dep[b]-*dep[c]+,d[a]+d[b]-*d[c]);
}
return ;
}
树链剖分
//O(n)-O(logn)
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
struct Edge
{
int b,c;
}es[maxn*];
int n,m=;
int first[maxn],next[maxn*];
void AddEdge(int a,int b,int c)
{
es[m]=(Edge){b,c};
next[m]=first[a];
first[a]=m++;
}
int dep[maxn],siz[maxn],son[maxn],fa[maxn],dis[maxn];
void dfs(int x)
{
siz[x]=; dep[x]=dep[fa[x]]+;
for(int i=first[x];i;i=next[i])
{
Edge& e=es[i];
if(e.b!=fa[x])
{
fa[e.b]=x;
dis[e.b]=dis[x]+e.c;
dfs(e.b);
siz[x]+=siz[e.b];
if(siz[son[x]]<siz[e.b]) son[x]=e.b;
}
}
}
int top[maxn];
void build(int x)
{
if(son[x])
{
top[son[x]]=top[x];
build(son[x]);
}
for(int i=first[x];i;i=next[i])
{
Edge& e=es[i];
if(e.b!=fa[x]&&e.b!=son[x])
{
top[e.b]=e.b;
build(e.b);
}
}
}
int query(int va,int vb)
{
int f1=top[va],f2=top[vb];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(va,vb);
}
va=fa[f1]; f1=top[va];
}
if(dep[va]>dep[vb]) swap(va,vb);
return va;
}
int main()
{
int a,b,c,Q;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,c);
}
dfs();
top[]=;
build();
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&a,&b);
c=query(a,b);
printf("%d %d\n",dep[a]+dep[b]-*dep[c]+,dis[a]+dis[b]-*dis[c]);
}
return ;
}
Tarjan算法(离线)
//O(n)-O(1)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int n,m;
int first[maxn],next[maxn*],to[maxn*],d[maxn*];
void AddEdge(int a,int b,int c)
{
to[++m]=b;
d[m]=c;
next[m]=first[a];
first[a]=m;
}
int f2[maxn],n2[maxn*],v[maxn*],id[maxn*];
void AddQuery(int a,int b,int c)
{
v[++m]=b;
id[m]=c;
n2[m]=f2[a];
f2[a]=m;
}
int vis[maxn],dis[maxn],dep[maxn],f[maxn],ans[maxn];
int findset(int x) {return x==f[x]?x:f[x]=findset(f[x]);}
void dfs(int x,int fa)
{
f[x]=x; dep[x]=dep[fa]+;
for(int i=first[x];i;i=next[i])
{
if(to[i]!=fa)
{
dis[to[i]]=dis[x]+d[i];
dfs(to[i],x);
f[to[i]]=f[x];
}
}
vis[x]=;
for(int i=f2[x];i;i=n2[i]) if(vis[v[i]]) ans[id[i]]=findset(v[i]);
}
int A[maxn],B[maxn];
int main()
{
scanf("%d",&n);
int a,b,c,Q;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,c);
}
scanf("%d",&Q);
m=;
for(int i=;i<Q;i++)
{
scanf("%d%d",&A[i],&B[i]);
AddQuery(A[i],B[i],i);
AddQuery(B[i],A[i],i);
}
dfs(,);
for(int i=;i<Q;i++) printf("%d %d\n",dep[A[i]]+dep[B[i]]-dep[ans[i]]*+,dis[A[i]]+dis[B[i]]-dis[ans[i]]*);
return ;
}
LCT
//O(n)-O(logn)
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=;
int n,m;
int first[maxn],next[maxn*],to[maxn*],d[maxn*];
void AddEdge(int a,int b,int c)
{
to[++m]=b;
d[m]=c;
next[m]=first[a];
first[a]=m;
}
int ans1,ans2;
struct LCT
{
int pre[maxn],ch[maxn][],fa[maxn],v[maxn],sumv[maxn],s[maxn];
void init()
{
memset(pre,,sizeof(pre));
memset(ch,,sizeof(ch));
s[]=fa[]=v[]=sumv[]=;
}
void maintain(int x)
{
sumv[x]=v[x]+sumv[ch[x][]]+sumv[ch[x][]];
s[x]=s[ch[x][]]+s[ch[x][]]+;
}
void rotate(int x,int d)
{
int y=pre[x],z=pre[y];
ch[y][d^]=ch[x][d];
pre[ch[x][d]]=y;
ch[z][ch[z][]==y]=x;
pre[x]=z;
ch[x][d]=y;
pre[y]=x;
maintain(y);
}
void splay(int x)
{
int rt=x;
while(pre[rt]) rt=pre[rt];
if(rt!=x)
{
fa[x]=fa[rt];
fa[rt]=;
while(pre[x]) rotate(x,ch[pre[x]][]==x);
}
maintain(x);
}
void access(int x)
{
int y=;
for(;x;x=fa[x])
{
splay(x);
fa[ch[x][]]=x;
pre[ch[x][]]=;
ch[x][]=y;
fa[y]=;
pre[y]=x;
y=x;
maintain(x);
}
}
void query(int x,int y)
{
access(y);
for(y=;x;x=fa[x])
{
splay(x);
if(!fa[x])
{
ans1=s[ch[x][]]+s[y]+;
ans2=sumv[ch[x][]]+sumv[y];
return;
}
fa[ch[x][]]=x;
pre[ch[x][]]=;
ch[x][]=y;
fa[y]=;
pre[y]=x;
y=x;
maintain(x);
}
}
}sol;
int vis[maxn];
queue<int> Q;
void BFS(int x)
{
vis[]=; Q.push();
while(!Q.empty())
{
x=Q.front(); Q.pop();
for(int i=first[x];i;i=next[i])
if(!vis[to[i]])
{
vis[to[i]]=;
sol.fa[to[i]]=x;
sol.v[to[i]]=d[i];
Q.push(to[i]);
sol.maintain(to[i]);
}
}
}
int main()
{
scanf("%d",&n);
int a,b,c,Q;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,c);
}
sol.init();
BFS();
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&a,&b);
sol.query(a,b);
printf("%d %d\n",ans1,ans2);
}
return ;
}
LCA的五种解法的更多相关文章
- LeetCode算法题-Number Complement(Java实现-五种解法)
这是悦乐书的第240次更新,第253篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第107题(顺位题号是476).给定正整数,输出其补码数.补充策略是翻转其二进制表示的位 ...
- LeetCode算法题-Longest Palindrome(五种解法)
这是悦乐书的第220次更新,第232篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第87题(顺位题号是409).给定一个由小写或大写字母组成的字符串,找到可以用这些字母构 ...
- LeetCode算法题-Find the Difference(Java实现-五种解法)
这是悦乐书的第214次更新,第227篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第82题(顺位题号是389).给定两个字符串s和t,它们只包含小写字母.字符串t由随机混 ...
- leetcode#42 Trapping rain water的五种解法详解
leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...
- LeetCode算法题-Power Of Three(Java实现-七种解法)
这是悦乐书的第204次更新,第215篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第71题(顺位题号是326).给定一个整数,写一个函数来确定它是否为3的幂.例如: 输入 ...
- LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)
这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个 ...
- LeetCode算法题-Reverse Vowels of a String(Java实现-四种解法)
这是悦乐书的第206次更新,第218篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第74题(顺位题号是345).编写一个函数,它将一个字符串作为输入,并仅反转一个字符串的 ...
- 16 级高代 II 思考题九的七种解法
16 级高代 II 思考题九 设 $V$ 是数域 $\mathbb{K}$ 上的 $n$ 维线性空间, $\varphi$ 是 $V$ 上的线性变换, $f(\lambda),m(\lambda)$ ...
- 学习笔记 - 快速傅里叶变换 / 大数A * B的另一种解法
转: 学习笔记 - 快速傅里叶变换 / 大数A * B的另一种解法 文章目录 前言 ~~Fast Fast TLE~~ 一.FFT是什么? 二.FFT可以干什么? 1.多项式乘法 2.大数乘法 三.F ...
随机推荐
- [ruby on rails] 跟我学之(3)基于rails console的查增删改操作
本章节展开对model的介绍:包括查增删改操作.紧接着上面一节<[ruby on rails] 跟我学之HelloWorld> 创建模型 使用命令创建模型 创建表post,默认自带两栏位 ...
- easyui-datagrid 两次请求
原因分析及解决方案 html代码中利用class声明了datagrid,导致easyUI解析class代码的时候先解析class声明中的datagrid,这样组件就请求了一次url:然后又调用js初始 ...
- Java和C#运行速度对比:Java比C#快约3倍
测试条件: Java版本: Java 8, .NET版本:v4.0, Release模式,针对x86平台优化 单线程模式. 测试1:(测试1的代码摘自http://blog.csdn.net/houj ...
- 【转】仿百度输入框智能提示的js代码
转自:http://www.jb51.net/article/40783.htm 对于我这个JS菜鸟,能找到这样的实属不容易啊!!! 刚开始老大让做这个功能,真是一点头绪都没有,万分感谢!!! 最近客 ...
- Java for LeetCode 023 Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解 ...
- Cocos2d-JS坐标系统
标准屏幕坐标系 如果接触过iOS,Android,Windows Phone等系统的应用开发,或使用DOM,CSS开发过Web网页,开发者会非常熟悉所谓的标准屏幕坐标系:左上角为原点,向右为X轴正方向 ...
- HDU1695 GCD (欧拉函数+容斥原理)
F - GCD Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- OSG addEventHandler W键 L键 F键
// add the state manipulator viewer->addEventHandler( new osgGA::StateSetManipulator(viewer-&g ...
- JAVA基础学习之throws和throw的区别、Java中的四种权限、多线程的使用等(2)
1.throws和throw的区别 throws使用在函数外,是编译时的异常,throw使用在函数内,是运行时的异常 使用方法 public int method(int[] arr) throws ...
- PHP 判断数组里的值是否有存在
一维数组检测<?php $a = array('as','ddf','ddf','as','qwe','wer','ert'); $res = array_unique($a); var_d ...