zoukankan      html  css  js  c++  java
  • 2017-10-24LCA

    今天复习LCA专题,做了几道题

    其一是codevs的2370-小机房的树极其裸的一道题

    是不是很裸?直接上代码了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 50010 
    int head[maxn],deep[maxn],dis[maxn];
    int ecnt,n,f[maxn][35];
    
    struct edge
    {
        int u,v,w;
        int next;
    }E[maxn<<1];
    
    void addedge(int u,int v,int w)
    {
        E[++ecnt].u = u;
        E[ecnt].v = v;
        E[ecnt].w = w;
        E[ecnt].next = head[u];
        head[u] = ecnt;
    }
    
    void dfs(int x,int fx)
    {
        deep[x] = deep[fx]+1;
        f[x][0] = fx;
        for(int i = head[x]; i ; i = E[i].next){
            int v = E[i].v;
            if(v == fx) continue;
            dis[v] = dis[x] + E[i].w;
            dfs(v,x);
        }
    }
    
    void init()
    {
        for(int j = 1; (1<<j) <= n; j ++)
            for(int i = 1; i <= n; i ++)
                if(deep[i] >= (1<<j))
                    f[i][j] = f[f[i][j-1]][j-1];
    }
    
    int getfather(int a,int b)
    {
        if(deep[a] < deep[b]) swap(a,b);
        int d = deep[a] - deep[b];
        for(int j = 30; j >= 0; j --)
            if(d&1<<j)
            {
                a = f[a][j];
            }
        if(a == b) return a;
        for(int j = 30; j >= 0 ; j --)
            if(f[a][j]!= f[b][j])
            {
                a = f[a][j];
                b = f[b][j];
            }
        return f[a][0];
    }
    
    int main()
    {
        scanf("%d",&n);int u,v,w,q;
        for(int i = 1; i < n; i ++)
        {
            scanf("%d%d%d",&u,&v,&w);
            u++;v++;
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dfs(1,0);
        init();
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&u,&v);
            u++;v++;
            int fx = getfather(u,v);
            printf("%d
    ",dis[u]+dis[v] - 2*dis[fx]);            
        }
    }

    第二题也是codevs1036-商务旅行

    这道题乍一看以为是最短路,但是它是树上的,所以我们可以直接求每两个点的LCA然后加起来就可以了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 30010
    using namespace std;
    int ecnt,head[maxn],deep[maxn],fa[maxn],top[maxn],size[maxn],son[maxn];
    struct edge
    {
        int u,v,next;
    }E[maxn<<1];
    
    void addedge(int u,int v)
    {
        E[++ecnt].u=u;
        E[ecnt].v=v;
        E[ecnt].next=head[u];
        head[u]=ecnt;
    }
    
    void dfs(int x)
    {
        size[x]=1;
        for(int i=head[x];i;i=E[i].next)
        {
            int v=E[i].v;
            if(fa[x]==v)continue;
            fa[v]=x;
            deep[v]=deep[x]+1;
            dfs(v);
            size[x]+=size[v];
            if(size[son[x]]<size[v])son[x]=v;    
        }
    }
    
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x];i;i=E[i].next)
        {
            int v=E[i].v;
            if(v==fa[x]||v==son[x])continue;
            dfs2(v,v);
        }
    }
    
    int lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            x=fa[top[x]];
        }
        return deep[x]>deep[y]?y:x;
    }
    
    int main()
    {
        int n,tmp,m,u,v,ans=0,a;
        scanf("%d",&n);
        for(int i=1;i<n;++i)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);    
        }
        dfs(1);dfs2(1,1);
        scanf("%d%d",&m,&tmp);
        for(int i=2;i<=m;++i)
        {
            scanf("%d",&a);
            ans+=deep[tmp]+deep[a]-deep[lca(a,tmp)]*2;
            tmp=a;
        }
        printf("%d",ans);
        return 0;
    } 

    第三道题是bzoj的1787

    这道题是求三个点的最近公共祖先,我们可以先求出每两个点的LCA k1,k2,k3然后比较,假设k1==k2那么肯定选k3为集结点,如果k1为集结点,那么肯定要有两个人从k3走过来,不满足最少的题意。有思路就很舒服了。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define maxn 500005
    using namespace std;
    int ecnt,head[maxn],siz[maxn],son[maxn],deep[maxn],fa[maxn],top[maxn],n,m;
    struct edge{
        int v,next;
    }E[maxn<<1];
    void add(int u,int v)
    {
        E[++ecnt].v=v;
        E[ecnt].next=head[u];
        head[u]=ecnt;
    }
    void dfs(int x)
    {
        siz[x]=1;
        for(int i=head[x] ; i ; i=E[i].next )
        {
            int v=E[i].v;
            if(fa[x]==v)continue;
            deep[v]=deep[x]+1;fa[v]=x;
            dfs(v);
            siz[x]+=siz[v];
            if(siz[son[x]]<siz[v])son[x]=v; 
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x] ; i ; i=E[i].next )
        {
            int v=E[i].v;
            if(son[x]==v||fa[x]==v)continue;
            dfs2(v,v);    
        } 
    }
    int lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            x=fa[top[x]];
        }
        return deep[x]<deep[y]?x:y;
    }
    inline int read()
    {
        int ret(0);
        char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
            ret=(ret<<1)+(ret<<3)+ch-'0';
            ch=getchar();
        }
        return ret;
    }
    int main()
    {
        int u,v,a,b,c,t1,t2,t3,jud,tmp,fu;
        n=read();m=read();
        for(int i=1 ; i<n ; ++i )
        {
            u=read();v=read();
            add(u,v);add(v,u);
        }
        dfs(1);dfs2(1,1);
        while(m--)
        {
            a=read();b=read();c=read();
            t1=lca(a,b);t2=lca(a,c);t3=lca(b,c);
            if(t1==t2)
            {
                fu=t3;
                jud=lca(t3,a);
                tmp=deep[b]+deep[c]+deep[a]-deep[t3]-deep[jud]*2;
            }
            if(t2==t3)
            {
                fu=t1;
                jud=lca(t1,c);
                tmp=deep[b]+deep[c]+deep[a]-deep[t1]-deep[jud]*2;
            }
            if(t1==t3)
            {
                fu=t2;
                jud=lca(t2,b);
                tmp=deep[b]+deep[c]+deep[a]-deep[t2]-deep[jud]*2;
            }
            printf("%d %d
    ",fu,tmp);
        }
        return 0;
    }
  • 相关阅读:
    cookie,session,token
    自己动手写一个简易对象关系映射,ORM(单例版和数据库池版)
    Python,针对指定文件类型,过滤空行和注释,统计行数
    MySQL 数据类型
    MySQL 基础小技巧
    Python测量时间,用time.time还是time.clock
    [计算机网络]想出网关?你需要懂得这些
    [数据结构与算法]05 Stack 经典面试题之判断字符串是否合法( Java 版)
    [自考总结]想要去的远方,终有一天会到达
    [数据结构与算法]04 Link List (链表)及单链表反转实现
  • 原文地址:https://www.cnblogs.com/xbygl/p/7725792.html
Copyright © 2011-2022 走看看