I

给一棵树,如果树上的某个节点被某个人占据,则它的所有儿子都被占据,lxh和pfz初始时分别站在两个节点上,谁当前所在的点被另一个人占据,他就输了比赛,问谁能获胜 

Input输入包含多组数据 
每组第一行包含两个数N,M(N,M<=100000),N表示树的节点数,M表示询问数,N=M=0表示输入结束。节点的编号为1到N。 
接下来N-1行,每行2个整数A,B(1<=A,B<=N),表示编号为A的节点是编号为B的节点的父亲 
接下来M行,每行有2个数,表示lxh和pfz的初始位置的编号X,Y(1<=X,Y<=N,X!=Y),lxh总是先移动 

Output对于每次询问,输出一行,输出获胜者的名字Sample Input

 2 1
 1 2
 1 2
 5 2
 1 2
 1 3
 3 4
 3 5
 4 2
 4 5
 0 0

Sample Output

 lxh
 pfz
 lxh

提示:

本题输入、输出都很多,请使用scanf和printf代替cin、cout。

我觉得这个题应该算水题(QAQ但是打比赛是没有看出来),

思路:维护一个树,然后用一个数组维护它的深度就行了。

AC:代码(592ms)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int n,m;
int vis[maxn],v[maxn];
int update(int x){
	if(x==v[x]) return 0;
	if(vis[x]!=0) return vis[x];
	return vis[x] = update(v[x])+1;
}
int main()
{
	while(~scanf("%d%d",&n,&m) && (n+m))
	{
		memset(vis,0,sizeof(vis));
		memset(v,0,sizeof(v));
		int a,b;
		for(int i = 1;i<=n-1;i++){
			scanf("%d %d",&a,&b);
			v[b] = a;
		}
		//for(int i = 1;i<=n;i++) printf("%d ",v[i]);
		//printf("
");
		int c = n;
		for(int i = 1;i<=n;i++) update(i);
		//for(int i = 1;i<=n;i++) printf("%d ",vis[i]);
		//printf("
");
		for(int i = 1;i<=m;i++){
			scanf("%d %d",&a,&b);
			//printf("%d %d
",vis[a],vis[b]);
			if(vis[a]<=vis[b]) printf("lxh
");
			if(vis[a]>vis[b]) printf("pfz
");
		}
	}
	
	return 0;
}


原文地址:https://www.cnblogs.com/Nlifea/p/11746042.html