1. 程式人生 > >最近在寫一些樹上的東西,先發一波LCA的吧!

最近在寫一些樹上的東西,先發一波LCA的吧!

++ 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]; 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 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的吧!