最近在寫一些樹上的東西,先發一波LCA的吧!
阿新 • • 發佈:2017-10-25
++ html str long ace efi algorithm quest http
不會樹剖的我只有去學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]; elsequest[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 he(ll x,ll y) { ll fx = find(x); ll fy = find(y); f[fx]= fy; } void dfs(ll fa,ll pos) { ceng[pos] = ceng[fa] + 1; for(ll i=head[pos];i;i=s[i].next) if(!ceng[s[i].v]) dfs(pos,s[i].v); } void tarjan(ll fa,ll pos) { for(ll i=head[pos];i;i=s[i].next) { if(zou[s[i].v] || 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; he(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(root,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) { v = s[i].v; if(!ceng[v]) dfs(now,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的吧!