zoukankan      html  css  js  c++  java
  • 人工栈——解决爆栈难题

    我们便以tarjan_LCA为模板,顺便复习复习tarjan_LCA。

    node (dfs)(dfs)

    #include<cstdio>
    #define N 500010 
    using namespace std;
    struct node{int v,fr;}e[N<<1];
    struct edge{int v,fr,num;}g[N<<1];
    int tail[N],head[N],lca[N],fa[N];
    int n,m,s,cnt=0,cnt1=0;
    bool bz[N];
    
    inline int read()
    {
    	int x=0; char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x;
    }
    
    inline void add(int u,int v) {e[++cnt]=(node){v,tail[u]}; tail[u]=cnt;}
    
    inline void add1(int u,int v,int num) {g[++cnt1]=(edge){v,head[u],num},head[u]=cnt1;}
    
    int find(int x) {return !fa[x] ? x:fa[x]=find(fa[x]);}
    
    void dfs(int x)
    {
    	for (int p=head[x],v;p;p=g[p].fr)
    	{
    		v=g[p].v;
    		if (!bz[v]) continue;
    		lca[g[p].num]=find(v);
    	}
    	for (int p=tail[x],v;p;p=e[p].fr)
    	{
    		v=e[p].v;
    		if (bz[v]) continue;
    		bz[v]=1,dfs(v),fa[v]=x;
    	}
    }
    
    int main()
    {
    	freopen("tarjan.in","r",stdin);
    	freopen("tarjan.out","w",stdout);
    	n=read(),m=read(),s=read();
    	for (int i=1,u,v;i<n;i++)
    		u=read(),v=read(),add(u,v),add(v,u);
    	for (int i=1,u,v;i<=m;i++)
    		u=read(),v=read(),add1(u,v,i),add1(v,u,i);
    	bz[s]=1,dfs(s);
    	for (int i=1;i<=m;i++) printf("%d
    ",lca[i]);
    	return 0;
    }
    

    这便是模板了(来源于jz_junior_oj_2263. 最近公共祖先(LCA))
    然后我们来看一看如何打人工栈。
    人工栈,顾名思义,就是人为的去模拟栈这个东东。
    我们要如何来模拟dfs呢?我们就按照dfs的性质来想想。
    它是不停地往下递归,所以我们也要如此
    我们用前向星来存储询问和边。
    每次走完一条边,我们就将tail数组更新一番。
    下面大概模拟一下这个过程:

    //dfs版
    void dfs(int x)
    {
    	'A';
    	for (int p=tail[x];p;p=e[p].fr)
    		if ('B')
    		{
    //			此处相当于'A'
    			dfs(e[p].v);
    			'C';
    		}
    //	此处相当于'C'
    }
    //人工栈版
    while (top)
    {
    	x=z[top];to=e[tail[x]].v;
    	while (!'B')
    		tail[x]=e[tail[x]].fr,to=e[tail[x]].v;
    	if (!tail[x])
    	{
    		'C';
    		top--;
    		continue;
    	}
    	'A';
    	z[++top]=to;
    }
    

    大概就是这样子的了,下面来看一看模板(开始的LCA)改成人工栈后的样子吧!

    node ()(人工栈)

    #include<cstdio>
    #define N 500010 
    using namespace std;
    struct node{int v,fr;}e[N<<1];
    struct edge{int v,fr,num;}g[N<<1];
    int tail[N],head[N],lca[N],fa[N],fat[N],z[N];
    int n,m,s,cnt=0,cnt1=0,top,x,to;
    bool bz[N];
    
    inline int read()
    {
    	int x=0; char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x;
    }
    
    inline void add(int u,int v) {e[++cnt]=(node){v,tail[u]}; tail[u]=cnt;}
    
    inline void add1(int u,int v,int num) {g[++cnt1]=(edge){v,head[u],num},head[u]=cnt1;}
    
    int gf(int x) {return !fa[x] ? x:fa[x]=gf(fa[x]);}
    
    int main()
    {
    	freopen("tarjan.in","r",stdin);
    	freopen("tarjan.out","w",stdout);
    	n=read(),m=read(),s=read();
    	for (int i=1,u,v;i<n;i++)
    		u=read(),v=read(),add(u,v),add(v,u);
    	for (int i=1,u,v;i<=m;i++)
    	{
    		u=read(),v=read();
    		if (u==v) {lca[i]=u; continue;}
    		add1(u,v,i),add1(v,u,i);
    	}
    	bz[s]=1;z[1]=s,top=1;
    	while (top)
    	{
    		x=z[top];
    		to=e[tail[x]].v;
    		while (tail[x] && bz[to])
    			tail[x]=e[tail[x]].fr,to=e[tail[x]].v;
    		if (!tail[x]) {fa[x]=fat[x],top--; continue;}
    		bz[to]=1,z[++top]=to,fat[to]=x;
    		for (int p=head[to],v;p;p=g[p].fr)
    		{
    			v=g[p].v;
    			if (!bz[v]) continue;
    			lca[g[p].num]=gf(v);
    		}
    	}
    	for (int i=1;i<=m;i++) printf("%d
    ",lca[i]);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    cnblog项目--20190309
    django js引入失效问题
    Python老男孩 day16 函数(六) 匿名函数
    Python老男孩 day16 函数(五) 函数的作用域
    Python老男孩 day15 函数(四) 递归
    Python老男孩 day15 函数(三) 前向引用之'函数即变量'
    Python老男孩 day15 函数(二) 局部变量与全局变量
    Python老男孩 day14 函数(一)
    Python老男孩 day14 字符串格式化
    Python老男孩 day14 集合
  • 原文地址:https://www.cnblogs.com/jz929/p/11817609.html
Copyright © 2011-2022 走看看