zoukankan      html  css  js  c++  java
  • 几种求LCA的姿势

     FZSZ Online Judge #815. LCA

    题目描述

    给定一个 n 个点的有根树,q 次询问 (x,y) 的最近公共祖先

    输入格式

    一行输入一个正整数 n

    以下 n1 行, 每行输入两个正整数 (x,y), 表示 xy有一条边

    一行输入一个正整数 q

    以下 q 行, 每行输入两个正整数 (x,y), 表示询问 lca(x,y)

    输出格式

    设第 i 次询问的答案为 xixi, 输出 qi=1nq-ixi(mod264)

    //不知道有没搞错反正是 ans = ans * n + Lca(x, y);

    样例输入

    3
    1 2
    1 3
    3
    1 2
    1 3
    2 3

    样例输出

    13

    数据范围

    n,q106,x,yn,

    倍增算法(在线处理)

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #define ull unsigned long long
    #define BIG 2333333
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using namespace std;
    ull mod;
    inline int read(){
    	char c;
    	while(c=getchar(),c>'9'||c<'0');
    	int data=c-48;
    	while(c=getchar(),c>='0'&&c<='9')
    		data=(data<<1)+(data<<3)+c-48;
    	return data;
    }
    int nxt[BIG],las[BIG],to[BIG],rd[BIG],dep[BIG],fa[BIG][24];
    int n,q,tot,x,y;
    ull ans;
    inline void add(int x,int y){
    	nxt[++tot]=las[x];
    	las[x]=tot;
    	to[tot]=y;
    	++rd[y];
    }
    inline void dfs(int now){
    	for(register int e=las[now];e;e=nxt[e]){
    		dep[to[e]]=dep[now]+1;
    		fa[to[e]][0]=now;
    		dfs(to[e]);
    	}
    }
    inline void ST(){
    	FOR(i,1,20)
    		FOR(j,1,n)
    			fa[j][i]=fa[fa[j][i-1]][i-1];
    }
    inline void swap(int &x,int &y){
    	int t=x;
    	x=y;
    	y=t;
    }
    inline int LCA(int x,int y){
    	if(dep[x]<dep[y])
    		swap(x,y);
    	for(register int i=20;i>=0;--i)
    		if(dep[fa[x][i]]>=dep[y])
    			x=fa[x][i];
    	if(x==y)
    		return x;
    	for(register int i=20;i>=0;--i)
    		if(fa[x][i]!=fa[y][i])
    			x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    int wr[101];
    inline void write(unsigned long long a){
    	if(!a){
    		putchar(48);
    		return;
    	}
    	while(a)
    		wr[++wr[0]]=a%10,a/=10;
    	while(wr[0])
    		putchar(48+wr[wr[0]--]);
    	return;
    }
    int main(){
    	n=read();
    	FOR(i,1,n-1){
    		x=read();
    		y=read();
    		add(x,y);
    	}
    	FOR(i,1,n)
    		if(!rd[i]){
    			dep[i]=1;
    			dfs(i);
    			break;
    		}
    	q=read();
    	ST();
    	mod=1;
    	FOR(i,1,63)
    		mod=(ull)(mod<<1);
    	while(q--){
    		x=read();
    		y=read();
    		ans=ans*n+LCA(x,y);
    		if(ans<0){
    			ans+=mod;
    			ans+=mod;
    		}
    	}
    	write(ans);
    	return 0;
    }
    

    树链剖分(在线处理)

    #include<cstdio>
    #include<iostream>
    #define BIG 2333333
    #define ll unsigned long long 
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using namespace std;
    namespace TCP{
    	int nxt[BIG],las[BIG],to[BIG],deg[BIG];
    	int dep[BIG],sz[BIG],top[BIG],f[BIG];
    	int n,m,x,y,tot;
    	inline void add(int x,int y){
    		nxt[++tot]=las[x];
    		las[x]=tot;
    		to[tot]=y;
    		++deg[y];
    		return;
    	}
    	inline void dfs1(int now){
    		sz[now]=1;
    		for(register int e=las[now];e;e=nxt[e]){
    			dep[to[e]]=dep[f[to[e]]=now]+1;
    			dfs1(to[e]);
    			sz[now]+=sz[to[e]];
    		}
    		return;
    	}
    	inline void dfs2(int now,int chain){
    		top[now]=chain;
    		register int i=0;
    		for(register int e=las[now];e;e=nxt[e])
    			if(sz[i]<sz[to[e]])
    				i=to[e];
    		if(!i)
    			return;
    		dfs2(i,chain);
    		for(register int e=las[now];e;e=nxt[e])
    			if(to[e]!=i)
    				dfs2(to[e],to[e]);
    		return;
    	}
    	inline ll lca(int u,int v){
    		for(;top[u]!=top[v];dep[top[u]]>dep[top[v]]?u=f[top[u]]:v=f[top[v]]);
    		return (ll)(dep[u]<dep[v]?u:v);
    	}
    };
    using namespace TCP; 
    namespace DATA{
    	inline void read(int &x){
    		char c;
    		while(c=getchar(),c>'9'||c<'0');
    		x=c-48;
    		while(c=getchar(),c>='0'&&c<='9')
    			x=(x<<1)+(x<<3)+c-48;
    		return;
    	}
    	int wr[51]; 
    	inline void write(ll x){
    		while(x)
    			wr[++wr[0]]=x%10,x/=10;
    		while(wr[0])
    			putchar(48+wr[wr[0]--]);
    		putchar('
    ');
    		return;
    	}
    };
    using namespace DATA;
    namespace WORK{
    	ll ans,mod=1ll;
    	inline void work(){
    		read(n);
    		FOR(i,1,n-1){
    			read(x);
    			read(y);
    			add(x,y);
    		}
    		FOR(i,1,n)
    			if(!deg[i]){
    				dfs1(i);
    				dfs2(i,i);
    				break;
    			}
    		FOR(i,1,63)
    			mod<<=1;
    		read(m);
    		while(m--){
    			read(x);
    			read(y);
    			ans=ans*n+lca(x,y);
    			if(ans<0){
    				ans+=mod;
    				ans+=mod;
    			}
    		}
    		write(ans); 
    	} 
    }; 
    using namespace WORK;
    int main(){
    	work();
    	return 0;
    } 
    

    Tarjan(离线处理)

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #define BIG 2333333
    #define ll unsigned long long 
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using namespace std;
    namespace TARJAN{
    	int n,m,tot;
    	int x,y,z;
    	int las[BIG],to[BIG],nxt[BIG],f[BIG],used[BIG],deg[BIG];
    	class question{
    		public:
    		int u[3];
    		int lca;
    		private:
    	}q[BIG];
    	vector<int>point[BIG>>1];
    	inline void add(int x,int y){
    		nxt[++tot]=las[x];
    		las[x]=tot;
    		to[tot]=y;
    		++deg[y];
    		return;
    	}
    	inline int find(int x){
    		return f[x]==x?x:f[x]=find(f[x]);
    	}
    	inline void dfs(int now,int fa){
    		used[now]=1;
    		register int i,p,other;
    		for(i=0;i<(int)point[now].size();++i){
    			p=point[now][i];
    			for(register int j=0;j<=1;++j){	
    				other=q[p].u[j];
    				if(other!=now)
    					if(used[other])
    						q[p].lca=find(other);
    			}
    		}
    		for(register int e=las[now];e;e=nxt[e])
    			dfs(to[e],now);
    		f[now]=fa;
    		return;
    	}
    }
    using namespace TARJAN; 
    namespace DATA{
    	inline void read(int &x){
    		char c;
    		while(c=getchar(),c>'9'||c<'0');
    		x=c-48;
    		while(c=getchar(),c>='0'&&c<='9')
    			x=(x<<1)+(x<<3)+c-48;
    		return;
    	}
    	int wr[51]; 
    	inline void write(ll x){
    		while(x)
    			wr[++wr[0]]=x%10,x/=10;
    		while(wr[0])
    			putchar(48+wr[wr[0]--]);
    		putchar('
    ');
    		return;
    	}
    };
    using namespace DATA;
    namespace WORK{
    	ll ans,mod=1ll;
    	inline void work(){
    		read(n);
    		FOR(i,1,n-1){
    			read(x);
    			read(y);
    			add(x,y);
    		}
    		FOR(i,1,n)
    			f[i]=i;
    		FOR(i,1,63)
    			mod<<=1;
    		read(m);
    		FOR(i,1,m){
    			read(q[i].u[0]);
    			read(q[i].u[1]);
    			point[q[i].u[0]].push_back(i);
    			point[q[i].u[1]].push_back(i); 
    		}
    		FOR(i,1,n)
    			if(!deg[i]){
    				dfs(i,0);
    				break;
    			}
    		FOR(i,1,m){
    			ans=(ll)(ans*n+q[i].lca);
    			if(ans<0){
    				ans+=mod;
    				ans+=mod;
    			}
    		}
    		write(ans);
    		return;
    	} 
    };
    using namespace WORK;
    int main(){
    	work();
    	return 0;
    } 
    

      

     

  • 相关阅读:
    php学习----文件系统
    zabbix添加mysql自定义监控项
    mysql主从库不同步问题
    zabbix分区
    CentOs7.3 安装 MySQL 5.7.21 二进制版本及主从配置
    MySQL数据备份之mysqldump使用
    mysql 占用大量写I/O
    zabbix添加企业微信发送
    Centos7 更新软件及删除多余内核
    zabbix监控vCenter报错
  • 原文地址:https://www.cnblogs.com/Stump/p/7687048.html
Copyright © 2011-2022 走看看