zoukankan      html  css  js  c++  java
  • 倍增法 求公共祖先

    倍增发:

          快速求祖先

       代码

    void dfs1(int u,int f)
    {
        fa[u]=f;
        vis[u]=1;
        dep[u]=dep[f]+1;
        for(ri i=1;(1<<i)<=dep[u];i++)
         anc[u][i]=anc[anc[u][i-1]][i-1];
         for(ri i=head[u];i;i=bian[i].net)
         {
             int v=bian[i].to;
             if(vis[v]==1) continue ;
               anc[v][0]=u;
               dfs1(v,u);
         }
    }
    View Code

       求公共祖先:

      

    int LCA(int x,int y)
    {
        if(dep[x]>dep[y]) swap(x,y);
        for(ri i=20;i>=0;i--)
        {
            if(dep[f[y][i]]>=dep[x])
            {
                y=f[y][i];
            }
            if(x==y) return x;
        }
        for(ri i=20;i>=0;i--)
        {
            if(f[x][i]!=f[y][i])
            {
                x=f[x][i],y=f[y][i];
            }
        }
        return f[x][0];
    }
    View Code

    找祖先:  一定要跟新

      题目:

    Panel 国将举办名为数字游戏的年度表演。每个省派出一名选手。
    
    国家有 nn 个编号从 11 到 nn 的省,每个省刚好有一条路径将其与其他省相连。第 ii 个省出来的代表有 2^i2 
    i
      名粉丝。
    
    今年,主席打算削减开支,他想要踢掉 kk 个选手。但是,被踢掉的选手的省将很 angry 并且不会让别的任何人从这个省经过。
    
    主席想确保所有剩下选手的省都互相可达,他也希望最大化参与表演的选手的粉丝数。
    
    主席该踢掉哪些选手呢?
    
    输入格式
    输入 n,kn,k 。( k < n leq 10^6k<n≤10 
    6
      )
    
    下来是 n-1n−1 行,一行两个数,代表一条道路的起终点。
    
    输出格式
    升序输出要踢掉的选手编号。
    View Code

     代码:

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ri register int
    const int M =2000005;
    const int N =1000005;
    int head[N];
    struct setbian{
        int net,to;
    }bian[M];
    int cent;
    void add(int a,int b)
    {
        bian[++cent].net=head[a],head[a]=cent;
        bian[cent].to=b;
    }
    int anc[N][30];
    int n,vis[N],fa[N],dep[N];
    void dfs1(int u,int f)
    {
        fa[u]=f;
        vis[u]=1;
        dep[u]=dep[f]+1;
        for(ri i=1;(1<<i)<=dep[u];i++)
         anc[u][i]=anc[anc[u][i-1]][i-1];
         for(ri i=head[u];i;i=bian[i].net)
         {
             int v=bian[i].to;
             if(vis[v]==1) continue ;
               anc[v][0]=u;
               dfs1(v,u);
         }
    }
    void dfs2(int u,int tp)
    {
        vis[u]=1;
        if(u==tp) return;
        dfs2(fa[u],tp);
    }
    int path[N],m;
    int main(){
        scanf("%d%d",&n,&m);
        m=n-m;
        memset(anc,-1,sizeof anc);
        for(ri i=1;i<n;i++)
        {
            int a,b;
            scanf("%ld%ld",&a,&b); 
            add(a,b);add(b,a);
        }
        dfs1(n,-1);
        memset(vis,0,sizeof vis);
        vis[n]=1;
        int help=1;
        for(ri i=n-1;i>=1;i--)
        {    
           int trmp=i;
            if(vis[i]==1) continue;
            for(ri j=20;j>=0;j--)
            {
                if(anc[i][j]==-1) continue;  
                if(vis[anc[trmp][j]]==0)   // 一定要跟新 
                 {
                   trmp=anc[trmp][j];break;
                 }
            }
            if(dep[i]-dep[trmp]+help+1<=m)
            dfs2(i,trmp),help+=dep[i]-dep[trmp]+1;
            if(help==m) break;    
        }
        int trmp=0;
        for(ri i=1;i<=n;i++) 
        {
            if(vis[i]==0) path[++trmp]=i;
        }
        for(ri i=1;i<=trmp;i++)
        printf("%d ",path[i]);                                                   
    }
    View Code

    1

      https://i-beta.cnblogs.com/posts/edit;postId=11760661

  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/11760661.html
Copyright © 2011-2022 走看看