最近在写一些树上的东西,先发一波LCA的吧!
Posted cc123321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近在写一些树上的东西,先发一波LCA的吧!相关的知识,希望对你有一定的参考价值。
不会树剖的我只有去学tarjan和倍增了,个人觉得倍增比tarjan好打一点。。。
tarjan学习的地方
http://www.cnblogs.com/JVxie/p/4854719.html
个人写的模板(洛谷的模板题,左右移符号打翻了,挑了好久QAQ)
#include<cstdio> #include<algorithm> #define ll long long #define maxn 500500 << 1 using namespace std; ll head[maxn],head_quest[maxn],tot,n,m,u,v,val,root,f[maxn],ceng[maxn],zou[maxn]; struct st{ ll v,next; }s[maxn]; struct que{ ll u,v,lca,next; que *es; }quest[maxn]; void add(ll u,ll v) { tot++; s[tot].v = v; s[tot].next = head[u]; head[u] = tot; } void addquest(ll u,ll v) { tot++; if(tot & 1) quest[tot].es = &quest[tot + 1]; else quest[tot].es = &quest[tot - 1]; quest[tot].u = u; quest[tot].v = v; quest[tot].next = head_quest[u]; head_quest[u] = tot; } ll find(ll x) { if(f[x] == x) return x; f[x] = find(f[x]); return f[x]; } void dfs(ll fa,ll pos) { ceng[pos] = ceng[fa] + 1; for(ll i=head[pos];i;i=s[i].next) if(s[i].v != fa) dfs(pos,s[i].v); } void tarjan(ll fa,ll pos) { for(ll i=head[pos];i;i=s[i].next) { if(s[i].v == fa) continue; tarjan(pos,s[i].v); } for(ll i=head_quest[pos];i;i=quest[i].next) { if(zou[quest[i].v]) { quest[i].lca = find(quest[i].v); quest[i].es -> lca = quest[i].lca; } } zou[pos] = 1; f[pos] = fa; } int main(){ scanf("%lld%lld%lld",&n,&m,&root); for(ll i=1;i<n;i++) { scanf("%lld%lld",&u,&v); add(u,v); add(v,u); } dfs(0,root); tot = 0; for(ll i=1;i<=m;i++) { scanf("%lld%lld",&u,&v); addquest(u,v); addquest(v,u); } for(ll i=1;i<=n;i++) f[i] = i; tarjan(0,root); for(ll i=1;i<=2*m;i+=2) printf("%lld\\n",quest[i].lca); }
接下来是倍增
学习:
http://www.cnblogs.com/FuTaimeng/p/5655616.html
自己写的模板(在洛谷交的时候忘了边要开两倍QAQ)
#include<cstdio> #include<algorithm> #include<cmath> #define maxn 1000500 #define ll long long using namespace std; struct st{ ll u,v,next; }s[maxn]; ll n,m,u,v,root,tot,head[maxn],ceng[maxn],fa[maxn][20]; inline void add(ll u,ll v) { tot++; s[tot].u = u; s[tot].v = v; s[tot].next = head[u]; head[u] = tot; } inline void dfs(ll f,ll now) { fa[now][0] = f; ceng[now] = ceng[f] + 1; for(ll i = head[now];i;i = s[i].next) { if(s[i].v != f) dfs(now,s[i].v); } } inline void init() { for(ll j=1;(1<<j)<=n;j++) for(ll i=1;i<=n;i++) fa[i][j] = fa[fa[i][j-1]][j-1]; } inline ll lca(ll a,ll b) { if(ceng[a] > ceng[b]) swap(a,b); ll cha = ceng[b] - ceng[a]; for(ll i = 0;(1 << i) <= cha;i++) { if((1 << i) & cha) b = fa[b][i]; } if(a != b) { for(ll i=(ll)log2(n);i>=0;i--) { if(fa[a][i] != fa[b][i]) { a=fa[a][i]; b=fa[b][i]; } } a = fa[a][0]; } return a; } int main(){ scanf("%lld%lld%lld",&n,&m,&root); for(ll i=1;i<n;i++) { scanf("%lld%lld",&u,&v); add(u,v); add(v,u); } dfs(0,root); init(); for(ll i=1;i<=m;i++) { scanf("%lld%lld",&u,&v); printf("%lld\\n",lca(u,v)); } }
以上是关于最近在写一些树上的东西,先发一波LCA的吧!的主要内容,如果未能解决你的问题,请参考以下文章