无聊的LCA
来源:互联网 发布:sqlserver教材 编辑:程序博客网 时间:2024/05/21 19:48
无聊的时候颓了一发LCA
首先,它有四种解法:
辣鸡的Tarjan,有时候很辣鸡的倍增,很快很快一点都不靠玄学树剖,还有凡是树剖做得到的它都做得到的LCT(尽管要加个log)
辣鸡的Tarjan
为什么很辣鸡:
因为它离线,所以辣鸡。
就算跑得再快,用不了当然辣鸡。
提前知道所有的(u,v),然后搞个并查集,dfs一遍,每次把孩子的集并入父亲,看它的对是否已并入,并入则记录答案,没并入继续跑。
int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}void Union(int x,int y) { fx=Find(x),fy=Find(y); if(fx==fy) return; fa[fy]=fx;}void Dfs(int x,int f) { f[x]=1; for(int i=from[x];i;i=q[i].next) if(f[q[i].to]) ans[q[i].numb]=Find(q[i].to); for(int i=head[x];i>=1;i=e[i].next) if(!f[e[i].to]) {Dfs(e[i].to);Union(x,e[i].to);}}
有时候很辣鸡的倍增
为什么说“有时候很辣鸡”,因为它是“严格的
void dfs(int x,int f) { pre[x][0]=f;dep[x]=dep[f]+1; for(int i=1;i<=logs&&pre[x][i];i++) pre[x][i]=pre[pre[x][i-1]][i-1]; for(int i=head[x];i;i=nxt[i]) if(to[i]!=f) dfs(to[i],x);}int LCA(int a,int b) { if(dep[a]>dep[b]) swap(a,b); for(int i=logs;i>=0;i--) if(dep[pre[b][i]]>=dep[a]) b=pre[b][i]; if(a==b) return a; for(int i=logs;i>=0;i--) if(pre[a][i]!=pre[b][i]) a=pre[a][i],b=pre[b][i]; return pre[a][0];}
“要是有人发现了错误请在下面指出”
最快的树剖
原理仍然不再累述,我只想说,虽然理论复杂度是当然长链剖分被卡也不关我的事
论如何把dfs缩到最短
int dfs(int x,int f) { fa[x]=f;size[x]=1;dep[x]=dep[f]+1; for(int i=head[x];i;i=nxt[i]) if(to[i]!=f) { dfs(to[i],x);size[x]+=size[to[i]]; if(size[to[i]]>size[son[x]]) son[x]=to[i]; }}int dfs2(int x,int f) { top[x]=f;if(son[x]) dfs2(son[x],f); for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);}int LCA(int x,int y) { for(;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]); return dep[x]<dep[y]?x:y;}
凡是树剖能干的它都能干的LCT
Splay的常数比
struct Link_Cut_Tree { int c[N][2],fa[N],sumv[N],val[N],q[N],top[N]; bool rev[N]; void pd(int x) { int &l=c[x][0],&r=c[x][1]; if(rev[x]) {rev[x]^=1;rev[r]^=1;rev[l]^=1;swap(r,l);} } bool isrt(int x) {return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void rot(int x) { int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; if(!isrt(y)) c[z][c[z][1]==y]=x; fa[c[x][r]]=y;fa[y]=x;fa[x]=z; c[y][l]=c[x][r];c[x][r]=y; } void splay(int x) { int top=0;q[++top]=x; for(int i=x;!isrt(i);i=fa[i]) q[++top]=fa[i]; for(;top;pd(q[top--])); for(int y,z;!isrt(x);rot(x)) if(!isrt(y=fa[x])) c[y][0]==x^c[z=fa[y]][0]==y?rot(x):rot(y); } int access(int x){ int last=0; for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,last=x; return last; } void makeroot(int x) {access(x);splay(x);rev[x]^=1;} void link(int x,int y) {makeroot(x);fa[x]=y;}}T;int main(){ int n=read(),m=read(),r=read(); for(int u,v,i=1;i<n;i++){ u=read(),v=read(); T.link(u,v); } T.makeroot(r); for(int u,v,ans;m--;){ u=read(),v=read(); T.access(u);ans=T.access(v); printf("%d\n",ans); } return 0;}
留个小BUFF
区间LCA求法<代码至今没有调过去>
嘛嘛嘛感谢这位m0哦,还有RMQ理论上是可以O(n)解决的但是我就不解决了(跑)
void dfs(int u,int d) { int i,v,w; for(vis[u]=true,ver[++tot]=u,fr[u]=tot,R[tot]=d,i=head[u];i;k=e[i].nxt) if(!vis[e[i].v]) dir[v=e[k].v]=dir[u]+e[i].w,dfs(v,d+1),ver[++tot]=u;R[tot]=d;}int LCA(int u ,int v) { int x=fr[u],y=fr[v]; if(x>y) swap(x,y); int K=(int)(log((double)(y-x+1))/log(2.0)); int a=dp[x][K],b=dp[y-_pow[K]+1][K]; if(R[a] < R[b]) return ver[a]; else return ver[b];}
0 0
- 无聊的LCA
- 无聊的
- 无聊写的无聊东西
- 无聊的圣诞节 无聊的周末 无聊的僵尸III
- 无聊的人做着无聊的事,说着无聊的话
- 无聊的工作,无聊的人
- 无聊的企业开发,无聊的业务。。。
- 无聊的人做无聊的事情
- 无聊的QQ,无聊的360
- 无聊的生活,无聊的世界
- 无聊的CSPROJ 文件,很无聊
- 无聊,让人感到窒息的无聊
- 无聊的下午
- 无聊的一天
- 无聊的生活!!!
- 无聊的ColorTransform
- 无聊的感言
- 无聊的组词
- 欢迎使用CSDN-markdown编辑器
- border
- java打印菱形
- 【脚本语言系列】关于Python测试工具lettuce, 你需要知道的事
- struts使用list提交多行表单(提供完整示例)
- 无聊的LCA
- POI 实现Excel文件中点击超链接跳转到某sheet页某列某行的功能
- python3+PyQt5 使用数据库窗口视图
- 大志天成凌金辉
- 运行第一个容器
- HTTP协议详解
- 3.在二维数组中查找
- Hive(十二)--Hive函数大全
- 类与对象