标准求法

//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的五种解法的更多相关文章

  1. LeetCode算法题-Number Complement(Java实现-五种解法)

    这是悦乐书的第240次更新,第253篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第107题(顺位题号是476).给定正整数,输出其补码数.补充策略是翻转其二进制表示的位 ...

  2. LeetCode算法题-Longest Palindrome(五种解法)

    这是悦乐书的第220次更新,第232篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第87题(顺位题号是409).给定一个由小写或大写字母组成的字符串,找到可以用这些字母构 ...

  3. LeetCode算法题-Find the Difference(Java实现-五种解法)

    这是悦乐书的第214次更新,第227篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第82题(顺位题号是389).给定两个字符串s和t,它们只包含小写字母.字符串t由随机混 ...

  4. leetcode#42 Trapping rain water的五种解法详解

    leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...

  5. LeetCode算法题-Power Of Three(Java实现-七种解法)

    这是悦乐书的第204次更新,第215篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第71题(顺位题号是326).给定一个整数,写一个函数来确定它是否为3的幂.例如: 输入 ...

  6. LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)

    这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个 ...

  7. LeetCode算法题-Reverse Vowels of a String(Java实现-四种解法)

    这是悦乐书的第206次更新,第218篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第74题(顺位题号是345).编写一个函数,它将一个字符串作为输入,并仅反转一个字符串的 ...

  8. 16 级高代 II 思考题九的七种解法

    16 级高代 II 思考题九  设 $V$ 是数域 $\mathbb{K}$ 上的 $n$ 维线性空间, $\varphi$ 是 $V$ 上的线性变换, $f(\lambda),m(\lambda)$ ...

  9. 学习笔记 - 快速傅里叶变换 / 大数A * B的另一种解法

    转: 学习笔记 - 快速傅里叶变换 / 大数A * B的另一种解法 文章目录 前言 ~~Fast Fast TLE~~ 一.FFT是什么? 二.FFT可以干什么? 1.多项式乘法 2.大数乘法 三.F ...

随机推荐

  1. RabbitMQ消息队列:ACK机制

    每个Consumer可能需要一段时间才能处理完收到的数据.如果在这个过程中,Consumer出错了,异常退出了,而数据还没有处理完成,那么 非常不幸,这段数据就丢失了. 因为我们采用no-ack的方式 ...

  2. Django之表单字段的选填与后台界面的管理

    参考: http://www.crazyant.net/1005.html http://gmingzhe.blog.51cto.com/810664/163051 所有的字段,默认blank=Fal ...

  3. 【转】maven导出项目依赖的jar包

    本文转自:http://my.oschina.net/cloudcoder/blog/212648 一.导出到默认目录 targed/dependency 从Maven项目中导出项目依赖的jar包:进 ...

  4. Sybase IQ导出文件的几种方式

    IQ有四种方法,将表的数据导出为文本文件:1.重定向 SELECT * FROM TABLE1 ># D:MYDATATABLE1.TXT -- 文件生成在执行语句的客户端上 2.通过选项导出 ...

  5. Android 中的Force Close

    今天写程序时遇到一个问题,领导希望在点击了setting里的force close 后,程序依然能够响应以前用alarmManager注册的receiver. 在网上看到了一些文章,写的是如何建立一个 ...

  6. HTML、CSS选择题

    Java EE软件工程师认证考试 试题库-选择题   一.    选择题(包括单选和双选) 1.D 以下(    )是HTML常用的块状标签(选择一项) A. <span> B. < ...

  7. sizeof(class)

    //#define _REENTRANT //#define _POSIX_C_SOURCE #include <iostream> #include <string> #in ...

  8. 学习Hadoop整体理解

    HDFS是Hadoop的核心模块之一,围绕HDFS是什么.HDFS的设计思想和HDFS的体系结构三方面来介绍. Hadoop的设计思想受到Google公司的GFS设计思想的启示,基于一种开源的理念实现 ...

  9. 1.单件模式(Singleton Pattern)

    意图:为了保证一个类仅有一个实例,并提供一个访问它的全局访问点. 1.简单实现(多线程有可能产生多个实例) public class CommonSigleton { /// <summary& ...

  10. Oracle如何操作级联删除

    级联删除即删除包含主键值的行的操作,该值由其它表的现有行中的外键列引用.在级联删除中,还删除其外键值引用删除的主键值的所有行. 语法: Foreign Key (column[,...n]) refe ...