LCA Tarjan实现
来源:互联网 发布:温州国际淘宝城网站 编辑:程序博客网 时间:2024/05/22 17:42
Tarjan LCA
以前认为Tarjan算法只是用来解强连通分量的算法,后来发现LCA也有一个Tarjan算法。
下面借一个树来了解一下算法思路。(树已经横向放置)
询问组:
11 9
10 8
6 7
2 3
这个算法最好亲手模拟一遍,然后就会感到茅塞顿开。
先从1节点开始DFS深度优先遍历(左节点优先)。
1->2->4->8->10。
发现10没有子节点,找所有关于10的询问,发现询问组有一个10和8的询问,检查发现vis[8]=0,说明8节点并没有被遍历完所有边或者根本就没有遍历过8节点,这样的话我们就不管它。
然后就把10标记上vis[10]=1,然后利用并查集,把它的(直接)父节点记录下来fa[10]=8。
然后就继续回退到8的下一个子节点,找到11,同理,检查询问组发现有11和9的询问,且vis[9]=0,跳过,vis[11]=1,fa[11]=8,回退至8。
8没有子节点可遍历了,检查询问组发现有关于8的询问10和8,而且vis[10]=1,那么我们就返回值fa[10]=8,10和8的LCA就是8,没有其余的关于8的询问了,vis[8]=1,fa[8]=4,回退至4。
4没有子节点可遍历了,检查询问组发现没有关于4的询问,那么就vis[4]=1,fa[4]=2,回退至2。
继续到5和9,9没有子节点可遍历了,检查询问组发现有关于9的询问8和9,而且vis[8]=1,那么我们就返回值findd(fa[8])=2,9和8的LCA就是2,那么就vis[9]=1,fa[9]=5,回退至5。
回退到5,没有询问,标记,回退。
2没有子节点可遍历了,检查询问组发现有关于2的询问2和3,且vis[3]=0,跳过,vis[2]=1,fa[2]=1,回退至1。
1有子节点可遍历,遍历1->3->6。
6没有子节点可遍历了,检查询问组发现有关于2的询问6和7,且vis[7]=0,跳过,vis[6]=1,fa[6]=3,回退至3。
1有子节点可遍历,遍历3->7。
7没有子节点可遍历了,检查询问组发现有关于7的询问6和7,且vis[6]=1,那么我们就返回值fa[6]=3,6和7的LCA就是3,没有其余的关于7的询问了,vis[7]=1,fa[7]=3,回退至3。
3没有子节点可遍历了,检查询问组发现有关于2的询问2和3,且vis[2]=1,那么我们就返回值fa[2]=1,2和3的LCA就是1,没有其余的关于3的询问了,vis[3]=1,fa[3]=1,回退至1。
1没有子节点可遍历了,检查询问组发现没有关于1的询问,结束算法。
鸣谢:yangbowen2同学的纠正!
代码实现比较简单。
代码:
#include<iostream>#include<cstdio>#include<cstdlib>#define MAXX 500001using namespace std;int temp=0,i,j,m,n,s;int tree_hd[MAXX],tree_y[MAXX*2],tree_nxt[MAXX*2];int ask_hd[MAXX],ask_y[MAXX*2],ask_nxt[MAXX*2];int ask_xx[MAXX],ask_yy[MAXX];int fa[MAXX],deep[MAXX],vis[MAXX];int ans[MAXX*4],ans_b[MAXX];int r(){ int aans=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { aans*=10; aans+=ch-'0'; ch=getchar(); } return aans*f;}void tree_add(int xx,int yy){ tree_y[++temp]=yy; tree_nxt[temp]=tree_hd[xx]; tree_hd[xx]=temp;}void ask_add(int xx,int yy){ ask_y[++temp]=yy; ask_nxt[temp]=ask_hd[xx]; ask_hd[xx]=temp;}int findd(int fdx){ if(fa[fdx]==fdx) return fdx; fa[fdx]=findd(fa[fdx]); return fa[fdx];}void dfs(int x){ int son; for(int p=tree_hd[x];p;p=tree_nxt[p]) { son=tree_y[p]; if(!deep[son]) { deep[son]=deep[x]+1; dfs(son); fa[son]=x; vis[son]=1; } } for(int qq=ask_hd[x];qq;qq=ask_nxt[qq]) { if(vis[ask_y[qq]]) { ans[qq]=findd(ask_y[qq]); } }}void write(int x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0');}int main(){ freopen("lca.in","r",stdin); freopen("lca.out","w",stdout); n=r(),m=r(),s=r(); int xx,yy; for(i=1; i<n; i++) { xx=r(),yy=r(); tree_add(xx,yy); tree_add(yy,xx); } for(i=1;i<=n;i++) { fa[i]=i; } for(j=1; j<=m; j++) { ask_xx[j]=r(),ask_yy[j]=r(); ask_add(ask_xx[j],ask_yy[j]); ask_add(ask_yy[j],ask_xx[j]); } deep[s]=1; dfs(s); for(i=1;i<=m;i++) { if(ans[i*2-1]) write(ans[i*2-1]),putchar(10); else if(ans[i*2]) write(ans[i*2]),putchar(10); else m++; }}
- LCA Tarjan实现
- POJ 1986 LCA,tarjan实现
- 最近公共祖先 LCA 倍增+Tarjan实现
- Tarjan LCA
- Tarjan lca
- Tarjan LCA
- tarjan--lca
- LCA 离线算法 tarjan
- lca---tarjan算法
- poj 1470--tarjan--LCA
- Tarjan&LCA题集
- POJ 3694 Tarjan+LCA
- LCA&&Tarjan算法
- HDU2586 离线tarjan LCA
- hdu 4547(tarjan LCA)
- hdu 4547(tarjan LCA)
- hdu 4547(tarjan LCA)
- LCA的Tarjan算法
- 最小生成树Kruskal算法学习
- 记一次unity下引入C++动态库跨平台打包的问题
- starfarming最短路
- eclipse怎么导入jar包
- 循环队列
- LCA Tarjan实现
- PHP摸索中的前端(1)搜索框
- Cocos2d-x Array Samples 数组初始化、字符转浮点值,数组纬度转换、字符串分割
- 利用Python实现多线程聊天功能
- 0/1背包问题
- post和get请求调用Http接口并拿到数据
- flume LineDeserializer Line length exceeds max (2048), truncating line!扩大一行数据量大小的采集上限
- 常用的jquery小技巧
- numpy入门——中级计算