• LCA模板



    /*
    ********--LCA模板--***************/ //设置好静态参数并构建好图的邻接表,然后调用lca_setquery()设置查询 //最后调用lca_start(),在lca::dfs中的your code处理每次查询 //复杂度O(M+Q) //表示图的邻接表 #define N 40100 #define MAX_Q 200 struct node { int to,next,w; }edge[2*N]; int pre[N],cnt; int ans[MAX_Q]; void add_edge(int u,int v,int w) { edge[cnt].w = w; edge[cnt].to = v; edge[cnt].next =pre[u]; pre[u] = cnt++; } struct LCA { int ln;//表示图中的点,默认范围为[1,n] int bin[N],bw[N]; // 并查集 与 bw记录到根节点的深度 struct node1 { int to,next; int id; }edge1[MAX_Q*2]; int pre1[N],cnt1; int lmark[N]; void init(int n)//初始化传入点的个数n { ln = n; cnt1 = 0; memset(pre1,-1,sizeof(pre1)); memset(lmark,0,sizeof(lmark)); for(int i=0;i<=n;i++) bin[i] = i; } void add_edge1(int u,int v,int id) { edge1[cnt1].id = id;//查询的id edge1[cnt1].to = v; edge1[cnt1].next = pre1[u]; pre1[u]=cnt1++; } int find(int v) { if(bin[v]==v) return v; return bin[v]=find(bin[v]); } void lca_setquery(int m) { //把所有的查询加入 //add_edge1(a,b); //add_edge1(b,a); for(int i=0;i<m;i++) { int a,b; scanf("%d%d",&a,&b); add_edge1(a,b,i); add_edge1(b,a,i); } } void dfs(int s,int w,int fa) { bw[s]=w; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if(v == fa) continue;//不到父亲节点 if(lmark[v]==0) { //dfs(v,w+1,s); dfs(v,w+edge[p].w,s); bin[v]=s; } } lmark[s] = 1; //遍历需要查询的点对 for(int p=pre1[s];p!=-1;p=edge1[p].next) { int v = edge1[p].to; if(lmark[v] == 1)//这个点已经处理过了 { int x = find(v); //最近公共祖先 int dis = bw[v]-bw[x]+bw[s]-bw[x];//两点之间在树上最近距离(这里默认树边为1) // your code //ans[ edge1[p].id ] = dis; // } } } void lca_start() { dfs(1,0,-1);//第一个参数表示根节点 } }lca; //给出大小为n的树,查询m次两点最短距离 //int main() //{ // int T; // cin>>T; // while(T--) // { // int n,m; // scanf("%d%d",&n,&m); // cnt = 0; // memset(pre,-1,sizeof(pre)); // for(int i=1;i<n;i++) // { // int a,b,c; // scanf("%d%d%d",&a,&b,&c); // add_edge(a,b,c); // add_edge(b,a,c); // } // // lca.init(n); // lca.lca_setquery(m); // lca.lca_start(); // for(int i=0;i<m;i++) printf("%d ",ans[i]); // } // return 0; //}

    2.LCA 在线建立rmq(nlog(n)) 查询(log(n))

    #define N 40040
    #define LN 20
    struct node
    {
        int to,next;
    }edge[2*N];
    
    int cnt,pre[N];
    
    void add_edge(int u,int v)
    {
        edge[cnt].to = v;
        edge[cnt].next = pre[u];
        pre[u] = cnt++;
    }
    
    struct Lca_Online
    {
        int _n;
        int deep[N];
        int dp[N][LN];
        void _dfs(int s,int fa,int dd)
        {
            deep[s] = dd;
            for(int p=pre[s];p!=-1;p=edge[p].next)
            {
                int v = edge[p].to;
                if(v == fa) continue;
                _dfs(v,s,dd+1);
                dp[v][0] = s;
            }
        }
        
        void _init()
        {
            for(int j=1;(1<<j)<=_n;j++)
            {
                for(int i=1;i<=_n;i++)
                {
                    if(dp[i][j-1]!=-1) dp[i][j] = dp[ dp[i][j-1] ][j-1];
                }
            }
        }
        void lca_init(int n)
        {
            _n = n;
            memset(dp,-1,sizeof(dp));
            //_dfs(firstid,-1,0);
            _dfs(1,-1,0);
            _init();
        }
        
        int lca_query(int a,int b)
        {
            if(deep[a]>deep[b]) swap(a,b);
            //调整b到a的同一高度
            for(int i=LN-1;deep[b]>deep[a];i--)
                if(deep[b]-(1<<i) >= deep[a]) b = dp[b][i];
            if(a == b) return a;
            for(int i=LN-1;i>=0;i--)
            {
                if(dp[a][i]!=dp[b][i]) a = dp[a][i],b = dp[b][i];
            }
            return dp[a][0];
        }
    }lca;
    
    //int d[N];
    //int main(int argc, const char * argv[]) {
    //    int T;
    //    cin>>T;
    //    while(T--)
    //    {
    //        memset(d,0,sizeof(d));
    //        cnt = 0;
    //        memset(pre,-1,sizeof(pre));
    //        int n;
    //        scanf("%d",&n);
    //        for(int i=1;i<n;i++)
    //        {
    //            int a,b;
    //            scanf("%d%d",&a,&b);
    //            add_edge(a, b);
    //            add_edge(b, a);
    //            d[b]++;
    //        }
    //        for(int i=1;i<=n;i++)
    //        {
    //            if(d[i] == 0) firstid = i;
    //        }
    //        int a,b;
    //        cin>>a>>b;
    //        lca.lca_init(n);
    //        printf("%d
    ",lca.lca_query(a, b));
    //    }
    //    return 0;
    //}
  • 相关阅读:
    ocos 信号量
    C 语言 输入字符串 并计算输入的字符的长度
    C 语言简历一个文件夹 并自己输入字符 来取文件夹名字
    C语言 创建一个 txt 文件 bin输入字符 保存文件在工作文件夹里
    C语言 之 printf () 函数你真的会用吗?
    Impala的命令COMPUTE STATS
    python 函数eval
    YouTube排名第一的励志英文演讲《Dream(梦想)》
    impala 表迁移方式 partquet数据文件移动方法
    Python中@staticmethod和@classmethod的作用和区别
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5632705.html
Copyright © 2020-2023  润新知