• CQYZ OJ|Contest 133|祖孙询问


    祖孙询问

    描述

    已知一颗有根树。有m个询问。每个询问给出了一对节点x,y,输出x,y的祖孙关系

    輸入

    第一行节点数目n接下来n行,每行一对整数a,b,表示a和b之间有边。如果b==-1,那么a就是数根接下来是一个整数m,表示询问的个数接下来m行,每行两个正整数x,y

    輸出

    对于每一个询问,如果x是y的祖先,输出1;如果y是x的祖先,输出2;否则输出0

    輸入範例 1

    10
    234 -1
    12 234
    13 234
    14 234
    15 234
    16 234
    17 234
    18 234
    19 234
    233 19
    5
    234 233
    233 12
    233 13
    233 15
    233 19
    

    輸出範例 1

    1
    0
    0
    0
    2
    

    提示

    对于30%的数据,n,m<=1000对于100%的数据,n,m<=40000,每个节点的编号都不超过40000

    思路

    将深的那个节点一直往上跳,跳到同一深度后如果是同一个节点那一个就是另一个的祖先。

    好吧大概搞懂什么是倍增了。

    第一次把树写到结构体里面。

    注意输入的两个节点中,后面那个是爸爸。

    Code

    #include<bits/stdc++.h> 
    using namespace std;
    
    const int MAXN=4e4+5,H=16;
    
    struct tree{
    	public:
    		void clear(void){
    			memset(e,0,sizeof(ed));
    			memset(head,0,sizeof(head));
    			memset(depth,0,sizeof(depth));
    			memset(f,0,sizeof(f));
    			newp=0;
    			bfsed=0;
    		}
    		
    		void vAdd(int p1,int p2){
    			++newp;
    			e[newp].to=p2;
    			e[newp].nex=head[p1];
    			e[newp].frm=p1;
    			fa[p2]=p1;
    			head[p1]=newp;
    		} 
    		
    		void setSize(int s){
    			size=s;
    			h=(log(size)/log(2)+0.5);
    		}
    		
    		int getSize(void){
    			return size;
    		}
    		
    		void setRoot(int r){
    			root_node=r;
    		}
    		
    		int root(void){
    			return root_node;
    		}
    		
    		int getDepth(int node){
    			if(!bfsed){
    				bfs_for_depth();
    			}
    			return depth[node];
    		}
    		
    		bool checkFa(int son,int fat){
    			for(int i=h;i>=0;--i){
    				if(depth[f[son][i]]>=depth[fat]){
    					son=f[son][i];
    				}
    			}
    			if(son==fat)return 1;
    			else return 0;
    		}
    		
    		
    	private:
    		struct ed{
    			int to,nex,frm;
    		} e[MAXN];
    		int head[MAXN],newp,size,root_node,depth[MAXN],fa[MAXN],f[MAXN][H];
    		bool bfsed;
    		int h;
    		
    		void bfs_for_depth(void){
    			queue<int> q;
    			depth[root_node]=1;
    			q.push(root_node);
    			while(!q.empty()){
    				int x=q.front();
    				q.pop();
    				for(int i=head[x];i;i=e[i].nex){
    					int y=e[i].to;
    					depth[y]=depth[x]+1;
    					f[y][0]=x;
    					for(int j=1;j<=h;++j){
    						f[y][j]=f[f[y][j-1]][j-1];
    					}
    					q.push(y);
    				}
    			}
    			bfsed=1;
    		}
    };
    
    tree a;
    
    int main(void){
    	a.clear();
    	int n,m;
    	scanf("%d",&n);
    	a.setSize(n);
    	for(int i=1;i<=n;++i){
    		int p1,p2;
    		scanf("%d%d",&p1,&p2);
    		if(p2==-1){
    			a.setRoot(p1);
    		}
    		else {
    			a.vAdd(p2,p1);
    		}
    	}
    	
    	scanf("%d",&m);
    	
    	for(int i=1;i<=m;++i){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		if(x!=y&&a.getDepth(x)==a.getDepth(y)){
    			printf("0
    ");
    		}
    		else{
    			int ans=0;
    			int dp1=a.getDepth(x);
    			int dp2=a.getDepth(y);
    			if(dp1>dp2){
    				if(a.checkFa(x,y)){
    					ans=2;
    				}
    			}
    			else{
    				if(a.checkFa(y,x)){
    					ans=1;
    				}
    			}
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    SQL Server中跨服务器跨数据库之间的数据增删改查
    Tomcat部署项目的方法
    java的位运算
    手机和邮箱格式验证
    Java实现List中某个对象属性中的字符串参数首字母进行排序
    springboot+dubbo+ZooKeeper+mybatis搭建分布式项目
    Java爬页面数据
    判断指定日期是否为节假日、双休日、工作日
    Java代码ping ip工具类
    Java生成压缩文件(zip、rar 格式
  • 原文地址:https://www.cnblogs.com/buringstraw/p/10124110.html
Copyright © 2020-2023  润新知