poj1330 LCA 屯个模板

//给一棵树,最后问两个点的lca是谁。
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;

const int maxn=10005;
struct node{
    int v,next;
};
node edge[maxn];
int head[maxn],cnt;
void add(int a,int b){
    edge[cnt].v=b;
    edge[cnt].next=head[a];
    head[a]=cnt++;
}

int deep[maxn<<1];//第i个访问的点的深度
int index[maxn<<1];//第i个访问的节点的编号
int first[maxn];//第i个节点最早出现的时候
int dp[maxn<<1][16];
int in[maxn];
int time;
void dfs(int u,int dep){
    index[++time]=u;
    deep[time]=dep;
    if(first[u]==0)
        first[u]=time;
    for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            dfs(v,dep+1);
            index[++time]=u;
            deep[time]=dep;
        }
}
void rmq_init(int n){
    int i,j;
    for(int i=1;i<=n;i++)
        dp[i][0]=i;
    for(int j=1;1<<j<=n;j++){
        int k=1<<(j-1);
        for(int i=1;i+k<n;i++){
            if(deep[dp[i][j-1]]<=deep[dp[i+k][j-1]])
                dp[i][j]=dp[i][j-1];
            else
                dp[i][j]=dp[i+k][j-1];
        }
    }
}
int rmq(int a,int b){
    int dis=abs(b-a)+1;
    int k=log(double(dis))/log(2.0);
    if(deep[dp[a][k]]<=deep[dp[b-(1<<k)+1][k]]){
        return dp[a][k];
    }
    else
        return dp[b-(1<<k)+1][k];
}

int LCA(int u,int v){
    return first[u]<=first[v]?index[rmq(first[u],first[v])] :index[rmq(first[v],first[u])];
}

void init(){
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(first,0,sizeof(first));
    memset(in,0,sizeof(in));
}

int main(){
    int n,m,q;
    int root=0;
    int u,v,d;
    int T;
    scanf("%d",&T);
    while(T--){
            scanf("%d",&n);
            int tmp=n;
            init();
            tmp--;
            while(tmp--){
                scanf("%d%d",&u,&v);
                add(u,v);
                in[v]++;
            }
            time=0;
            for(int i=1;i<=n;i++){
                if(in[i]==0){
                    dfs(i,0);
                    break;
                }
            }
            rmq_init(time);
            scanf("%d%d",&u,&v);
           printf("%d\n",LCA(u,v));
    }
return 0;
}

版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/hitwhacmer1

时间: 2024-10-06 14:27:48

poj1330 LCA 屯个模板的相关文章

HDU 2586 How far away ? (离线LCA Tarjan算法模板)

How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6422    Accepted Submission(s): 2411 Problem Description There are n houses in the village and some bidirectional roads connecting

LCA倍增【模板】

1 #include <algorithm> 2 #include <cstdio> 3 #include <vector> 4 5 #define N 10015 6 7 using namespace std; 8 9 vector<int>vec[N]; 10 int n,a,b,m,deep[N],dad[N][100]; 11 12 int LCA(int x,int y) 13 { 14 if(deep[x]>deep[y]) swap(x

poj1330 lca 最近公共祖先问题学习笔记

首先推荐两个博客网址: http://dongxicheng.org/structure/lca-rmq/ http://scturtle.is-programmer.com/posts/30055.html [转]tarjan算法的步骤是(当dfs到节点u时): 1 在并查集中建立仅有u的集合,设置该集合的祖先为u 1 对u的每个孩子v:    1.1 tarjan之    1.2 合并v到父节点u的集合,确保集合的祖先是u 2 设置u为已遍历 3 处理关于u的查询,若查询(u,v)中的v已遍

POJ1330(LCA入门题)

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 23388   Accepted: 12195 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each

学习 LCA&amp;&amp;RMQ

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

LCA&amp;&amp;RMQ问题

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

poj 3417 Network 【LCA】【树中增新边后 求每条树边被环所覆盖的次数】

Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4251   Accepted: 1223 Description Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried because she has just received a bad news which denotes that DxtNet

HDU 2586 LCA离线算法 tarjan算法

LCA tarjan算法模板题 题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离. 用tarjan离线算法算出每个询问的两点的最近公共祖先 ans[i]=dis[x[i]]+dis[y[i]]-2*dis[z[i]]; //  x[i],y[i]分别存储每次询问的两点,z[i]存储这两点的最近公共祖先 #include "stdio.h" #include "string.h" int tot,n,m; int f[40010],x[40010],y[4

笔记:LCA最近公共祖先 Tarjan(离线)算法

LCA最近公共祖先 Tarjan他贱(离线)算法的基本思路及其算法实现 本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先简称LCA(Lowest Common Ancesto