数据结构入门9—虚树
来源:互联网 发布:红警2尤复简体优化版 编辑:程序博客网 时间:2024/06/01 08:56
原本以为K-D Tree比虚树难,但是后来发现虚树反而难理解一些。主要是关于找LCA的问题。
假如我们有一些点是一定要在虚树里的,那么需要保证他们任意两点的LCA也在虚树里,否则树的结构就改变了。
那么就需要用到dfs序了。
我们求得每个点的dfs序,然后把这些点按dfs序排序,那么他们所有的LCA肯定是排序后某相邻两点的LCA。这个是可以证明的,我就不证了。
然后找到LCA之后就是找每个节点的虚树父亲问题了,把找到的新节点(就是找到的LCA)与原来所有节点一起按照dfs序再排一次序,因为我们可以在初始化时找出每个点所在子树的最大最小时间戳,所以可以维护一个栈然后判断当前节点是否为栈内节点的原图中的子孙,若不是就弹栈,否则就是我们要找的父亲。
模板题链接
//Serene#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<set>using namespace std;const long long maxn=250000+10,INF=2e9;long long n,m,mi[20]; long long dp[maxn],len[maxn],node[maxn],zz[maxn];int vis[maxn],fath[maxn]; long long aa;char cc;long long read() { aa=0;cc=getchar(); while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa;} int fir[maxn],nxt[2*maxn],to[2*maxn];long long v[2*maxn],e=0;void add(int x,int y,int z) { to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z; to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;} int fa[maxn][20],id[maxn],end[maxn],dep[maxn],tot,maxd;void dfs(int pos,int d,long long minnum) { dep[pos]=d;id[pos]=++tot;len[pos]=minnum; maxd=max(maxd,d); for(int y=fir[pos];y;y=nxt[y]) { if(to[y]==fa[pos][0]) continue; fa[to[y]][0]=pos; dfs(to[y],d+1,min(v[y],minnum)); } end[pos]=tot;} bool cmp(const int x,const int y) { return id[x]<id[y];} int getlca(int x,int y) { if(dep[x]!=dep[y]) { if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y]; for(int i=18;i>=0;--i) if(mi[i]<=cha){ cha-=mi[i]; x=fa[x][i]; if(!cha) break; } } int xx,yy,z; while(x!=y) { xx=x; yy=y; z=0; while(xx!=yy) { x=xx; y=yy; xx=fa[xx][z];yy=fa[yy][z]; z++; } if(z==1) { x=xx; y=yy; } } return x;} int main() { n=read(); int x,y,z,xx; for(int i=1;i<n;++i) { x=read();y=read();z=read(); add(x,y,z); } dfs(1,1,INF); mi[0]=1;for(int i=1;i<=18;++i) mi[i]=mi[i-1]*2; for(int i=1;mi[i]<=maxd+1;++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; m=read(); for(int qaq=1;qaq<=m;++qaq) { x=read(); for(int i=1;i<=x;++i) node[i]=read(),vis[node[i]]=1; sort(node+1,node+x+1,cmp); xx=x;// for(int i=2;i<=xx;++i) { z=getlca(node[i-1],node[i]); if(!vis[z]) node[++x]=z,vis[z]=2; } if(!vis[1]) node[++x]=1,vis[1]=2; sort(node+1,node+x+1,cmp); y=1;zz[1]=node[1];dp[node[1]]=0; for(int i=2;i<=x;++i) { dp[node[i]]=len[node[i]]; while(y&&id[node[i]]>end[zz[y]]) y--; fath[node[i]]=zz[y];dp[zz[y]]=0; zz[++y]=node[i];// } for(int i=x;i>1;i--) { if(vis[node[i]]==2) dp[node[i]]=min(dp[node[i]],len[node[i]]);// else dp[node[i]]=len[node[i]]; dp[fath[node[i]]]+=dp[node[i]]; } printf("%lld\n",dp[node[1]]); for(int i=1;i<=x;++i) vis[node[i]]=0; } return 0;}
阅读全文
0 0
- 数据结构入门9—虚树
- 数据结构入门——递归
- 笔记——数据结构入门
- 数据结构入门1—Treap
- 数据结构入门5—分块
- 数据结构入门7—左偏树
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- Python一天入门9:数据结构-元组
- 数据结构入门——栈与队列
- 数据结构入门——动态数组
- 笔记——数据结构入门(二)
- Python入门——基本数据结构
- codeforces 405 B Domino Effect (模拟)
- 3.Lua变量和字符串处理
- java9新特性
- MFC多文档应用程序同时显示两个视图
- 怎么给Eclipse Spring插件
- 数据结构入门9—虚树
- 暑假训练总结
- 精确率和召回率
- 4.Lua条件判断和循环语句
- 5.Lua表和函数语法
- CDN工程师:还没用上TLS1.2- 那就直接升级到TLS1.3吧
- 6.Lua调用c++函数传递普通参数
- 出现javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
- 用html做一个图片切换