其他分享
首页 > 其他分享> > 2021.8.21 北中暑训

2021.8.21 北中暑训

作者:互联网

上午,学习了倍增求LCA

例题

看了题目我先是把树剖lca代码打了(因为树剖的代码比较好理解)

代码如下:

#include<bits/stdc++.h>
using namespace std;
int cnt,n,m,s,dd[1000001],zs[1000001],f[1000001],sd[1000001],ss[1000001],maxn,next[1000001],head[1000001],to[1000001];
inline void add(register int u,register int v)
{
    next[++cnt]=head[u];
    head[u]=cnt;
    to[cnt]=v;
}
int js(int x,int y,int z)
{
    f[x]=y;
    sd[x]=z;
    ss[x]=1;
    maxn=-1;
    for(int i=head[x];i!=0;i=next[i])
    {
        if(to[i]!=y)
        {
            ss[x]+=js(to[i],x,z+1);
            if(ss[to[i]]>maxn)
            {
                maxn=ss[to[i]];
                zs[x]=to[i];
            }
        }
    }
    return ss[x];
}
void lb(int x,int y)
{
    dd[x]=y;
    if(zs[x]==0)
    {
        return;
    }
    lb(zs[x],y);
    for(int i=head[x];i!=0;i=next[i])
    {
        if(dd[to[i]]==0)
        {
            lb(to[i],to[i]);
        }
    }
}
int qz(int x,int y)
{
    while(dd[x]!=dd[y])
    {
        if(sd[dd[x]]<sd[dd[y]])
        {
            swap(x,y);
        }
        x=f[dd[x]];
    }
    if(sd[x]<sd[y])
    {
        return x;
    }
    else
    {
        return y;
    }
}
int main()
{
    int x,y;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    js(s,0,1);
    lb(s,s);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",qz(x,y));
    }
    return 0;
}

然后再学习倍增的lca,专研了一会,就向zx同学强请制教(物理)了

zx奆佬讲的思路很容易理解,但代码要下点功夫(主要是我脑子不好,不像隔壁zx同学秒切).

倍增的代码如下:

#include<bits/stdc++.h>
using namespace std;
int cnt,n,m,s,sd[1000001],f[1000001][31],next[1000001],head[1000001],to[1000001];
inline void add(register int u,register int v)
{
    next[++cnt]=head[u];
    head[u]=cnt;
    to[cnt]=v;
}
void js(int x,int y)
{
    sd[x]=sd[y]+1;
    for(int i=1;(1<<i)<=sd[x];++i)
    {
        f[x][i]=f[f[x][i-1]][i-1];
    } 
    for(int i=head[x];i!=0;i=next[i])
    {
        if(to[i]!=y)
        {
            f[to[i]][0]=x;
            js(to[i],x);
        }
    }
    return;
}
int lca(int x,int y)
{
    if(sd[x]<sd[y])
    {
        swap(x,y);
    }
    for(int i=20;i>=0;i--)
    {
        if(sd[f[x][i]]>=sd[y])
        {
            x=f[x][i];
        }
        if(x==y)
        {
            return x;
        }
    }
    for(int i=20;i>=0;i--)
    {
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}
int main()
{
    int x,y;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    js(s,0);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}

 

下午,写了一些初赛的题与LCA的题

总的来说还不错.

今天又TM是开森的一天呢!

标签:cnt,int,2021.8,北中,head,1000001,next,暑训,sd
来源: https://www.cnblogs.com/zhangpuwen/p/15170936.html