zoukankan      html  css  js  c++  java
  • 洛谷3379

    lca问题

    1.树链剖分

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define maxn 500001
    using namespace std;
    int n,m,s,cnt,head[maxn],to[maxn<<1],nex[maxn<<1];
    int fa[maxn],dep[maxn],id[maxn],a[maxn],top[maxn],siz[maxn],son[maxn];
    
    inline void read(int &x){
        char ch=getchar();x=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    }
    
    void addedge(int u,int v){
        to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;
    }
    
    void dfs1(int x,int f){
        dep[x]=dep[f]+1;fa[x]=f;siz[x]=1;
        int maxson=-1;
        for(int i=head[x];i;i=nex[i]){
            int v=to[i];
            if(v==f)continue;
            dfs1(v,x);
            siz[x]+=siz[v];
            if(siz[v]>maxson){son[x]=v;maxson=siz[v];}
        }
    }
    
    inline void dfs2(int x,int topf){
        id[x]=++cnt;
        a[cnt]=x;
        top[x]=topf;
        if(!son[x])return;
        dfs2(son[x],topf);
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(y==fa[x]||y==son[x])continue;
            dfs2(y,y);
        }
    }
    int query(int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);//尤其要注意这里是dep[top[x]]<dep[top[y]],而非dep[x]<dep[y]
            x=fa[top[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    
    int main(){
        read(n);read(m);read(s);
        for(int i=1;i<n;i++){
            int u,v;read(u);read(v);addedge(u,v);addedge(v,u);
        }
        cnt=0;
        dfs1(s,s);dfs2(s,s);
        for(int i=1;i<=m;i++){
            int u,v;read(u);read(v);printf("%d\n",query(u,v));
        }
    }

    2.tarjan算法

    遍历一棵树,不断更新当前节点子节点的父亲。。。具体可看代码,不难

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #define maxn 500002
    using namespace std;
    int n,m,s,cnt,ans[maxn],fa[maxn],h[maxn],head[maxn],to[maxn<<1],nex[maxn<<1];
    struct data{int v,id,ans,nex;}q[maxn<<1];
    bool vis[maxn];
    
    inline void read(int &x){
        char ch=getchar();x=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    }
    
    void addedge(int u,int v){
        to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;
    }
    
    void add(int u,int v,int id){
        q[++cnt].v=v;q[cnt].id=id;q[cnt].nex=h[u];h[u]=cnt;
    }
    
    int findfa(int x){
        if(fa[x]==x)return x;return fa[x]=findfa(fa[x]);
    }
    
    void unio(int x,int y){
        int fx=findfa(x),fy=findfa(y);
        fa[fx]=fy;
    }
    
    void lca(int now,int fa){
        for(int i=head[now];i;i=nex[i]){
            if(to[i]==fa)continue;
            lca(to[i],now);
            unio(to[i],now);
        }
        vis[now]=1;
        for(int i=h[now];i;i=q[i].nex){
            if(vis[q[i].v])
            ans[q[i].id]=findfa(q[i].v);
        }
    }
    
    int main(){
        read(n);read(m);read(s);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<n;i++){
            int u,v;
            read(u);read(v);
            addedge(u,v);addedge(v,u);
        }
        cnt=0;
        for(int i=1;i<=m;i++){
            int u,v;
            read(u);read(v);
            add(u,v,i);add(v,u,i);
        }
        lca(s,0);
        for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
    }

    3.dfs+倍增

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define maxn 500005
    using namespace std;
    int n,m,s,head[maxn],ln[500005],st[maxn][22],dep[maxn];
    struct data{int v,nxt;}edge[maxn*2];
    
    inline int read(){
    	char ch=getchar();int k=0;
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-'0';ch=getchar();}
    	return k;
    }
    
    void dfs(int now,int fa){
    	dep[now]=dep[fa]+1;
    	st[now][0]=fa;
    	for(int i=1;(1<<i)<=dep[now];i++)st[now][i]=st[st[now][i-1]][i-1];
    	for(int i=head[now];i;i=edge[i].nxt)if(edge[i].v!=fa)dfs(edge[i].v,now);
    }
    
    int lca(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	while(dep[x]>dep[y])x=st[x][ln[dep[x]-dep[y]]-1];
    	if(x==y)return x;
    	for(int j=ln[dep[x]]-1;j>=0;j--)//
    	   if(st[x][j]!=st[y][j]) x=st[x][j],y=st[y][j];
    	   return st[x][0];
    }
    
    int main(){
    	n=read();m=read();s=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		edge[i*2-1].v=v;edge[i*2-1].nxt=head[u];head[u]=i*2-1;
    		edge[i*2].v=u;edge[i*2].nxt=head[v];head[v]=i*2;
    	}
    	dfs(s,0);
    	for(int i=1;i<=n;i++)ln[i]=ln[i-1]+((1<<ln[i-1])==i);//可以直接公式求,懒得改了
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();
    		printf("%d\n",lca(x,y));
    	}
    	return 0;
    }

  • 相关阅读:
    GAN阶段性小结(损失函数、收敛性分析、训练技巧、应用“高分辨率、domain2domain”、研究方向)
    MMD :maximum mean discrepancy
    Chinese-BERT-wwm
    VGG16学习笔记
    jupyter notebook使用技巧--命令行模式以及在Markdown模式使用的操作(4)
    不同领域公开数据集下载
    数据挖掘竞赛,算法刷题网址汇总
    在keras下实现多个模型的融合
    问题集合
    开源测试数据集合
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/8833791.html
Copyright © 2011-2022 走看看