LCA最近公共祖先(RMQ、Tarjan)

来源:互联网 发布:cda数据分析师难嘛 编辑:程序博客网 时间:2024/06/05 05:07

题目:http://poj.org/problem?id=1330

讲解:http://blog.csdn.net/tingyun_say/article/details/52092464

离线算法:dfs+并查集(Tarjan)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<vector>using namespace std;const int N=1e4+107;const int inf=0x3f3f3f3f;int n,q1,q2;int f[N],a[N];bool c[N],flag[N];vector<int> v[N];int find(int k){    if(f[k]==k) return k;    f[k]=find(f[k]);    return f[k];}int unions(int x,int y){    int xx=find(x),yy=find(y);    f[yy]=xx;    return 0;}int tarjan(int u){    for(int i=0;i<v[u].size();i++)    {        tarjan(v[u][i]);        unions(u,v[u][i]);        a[find(u)]=u;    }    c[u]=1;    if(q1==u&&c[q2]) printf("%d\n",a[find(q2)]);    else if(q2==u&&c[q1]) printf("%d\n",a[find(q1)]);    return 0;}int main(){    int t,i;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i=1;i<=n;i++)        {            v[i].clear();            f[i]=i;            a[i]=0;            c[i]=0;            flag[i]=1;        }        for(i=1;i<n;i++)        {            int x,y;            scanf("%d%d",&x,&y);            flag[y]=0;            v[x].push_back(y);        }        scanf("%d%d",&q1,&q2);        for(i=1;i<=n;i++) if(flag[i]) break;        tarjan(i);    }    return 0;}
在线算法:dfs+RMQ(RMQ)
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<vector>using namespace std;const int N=1e4+107;const int inf=0x3f3f3f3f;const int log=20;int dp[N][log],depth[N],deg[N];struct node{    int to;    node *next;}g[2*N],*cur,*head[N];void addnode(int u,int v){    cur->to=v;    cur->next=head[u];    head[u]=cur++;}void dfs(int u){    depth[u]=depth[dp[u][0]]+1;    for(int i=1;i<log;i++) dp[u][i]=dp[dp[u][i-1]][i-1];    for(node *it=head[u];it;it=it->next) dfs(it->to);}int lca(int u,int v){    if(depth[u]<depth[v]) swap(u,v);    for(int st=1<<(log-1),i=log-1;  i>=0   ;i--,st>>=1)        if(st<=depth[u]-depth[v]) u=dp[u][i];    if(u==v) return u;    for(int i=log-1;i>=0;i--)        if(dp[v][i]!=dp[u][i])        v=dp[v][i],u=dp[u][i];    return dp[u][0];}void init(int n){    for(int i=0;i<=n;i++)    {        dp[i][0]=0;        head[i]=NULL;        deg[i]=0;    }    cur=g;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,u,v;        scanf("%d",&n);        init(n);        for(int i=0;i<n-1;i++)        {            scanf("%d%d",&u,&v);            addnode(u,v);            deg[v]++;            dp[v][0]=u;        }        for(int i=1;i<=n;i++)            if(deg[i]==0){dfs(i);break;}        scanf("%d%d",&u,&v);        printf("%d\n",lca(u,v));    }}
HDU  2586
Lca#define N 50005vector<int> mp[N],w[N],query[N],num[N];int p[N],d[N],res[N];bool vis[N];int n;void Init(){    int i;    for(i=1;i<=n;i++)    {        mp[i].clear();        w[i].clear();        query[i].clear();        num[i].clear();        p[i]=i;        d[i]=0;        vis[i]=false;    }}int Find(int x){    if(p[x]!=x)        p[x]=Find(p[x]);    return p[x];}void Union(int x,int y){    x=Find(x);    y=Find(y);    if(x!=y)        p[y]=x;}void Tarjan(int cur,int v){    int size,i,tmp;    vis[cur]=true;    d[cur]=v;    size=mp[cur].size();    for(i=0;i<size;i++)    {        tmp=mp[cur][i];        if(vis[tmp]) continue;        Tarjan(tmp,v+w[cur][i]);        Union(cur,tmp);    }    size=query[cur].size();    for(i=0;i<size;i++)    {        tmp=query[cur][i];        if(!vis[tmp])continue;        res[num[cur][i]]=d[cur]+d[tmp]-2*d[Find(tmp)];    }}int main(){    int T,q,a,b,c,i;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&q);        Init();        for(i=1;i<n;i++)        {            scanf("%d%d%d",&a,&b,&c);            mp[a].push_back(b);            w[a].push_back(c);            mp[b].push_back(a);            w[b].push_back(c);        }        for(i=0;i<q;i++)        {            scanf("%d%d",&a,&b);            query[a].push_back(b);            query[b].push_back(a);            num[a].push_back(i);            num[b].push_back(i);        }        Tarjan(1,0);        for(i=0;i<q;i++)            printf("%d\n",res[i]);    }    return 0;}


0 0