题目链接:https://vjudge.net/contest/323985#problem/L
给一棵树,如果树上的某个节点被某个人占据,则它的所有儿子都被占据,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
对于每次询问,输出一行,输出获胜者的名字
分析:
对于树这种数据结构,如下图:2号节点是上一层(1)的子节点,又是下一层(4,5)的根节点。对于一棵树只有一个根节点,对应的,也只有根节点有f[u]=u;给出两个点的初始位置,可以通过比较点到根节点的距离,来判断输赢。
注意的是(sum初始化为1):再找祖先的时候,不进行路径压缩,从当前位置一直到根节点f[u]=u才结束while循环。
int getf(int u,int sum)
{
while(u!=f[u])/*直至到根节点*/
{
sum++;
u=f[u];
}
return sum;
}
代码:
#include<cstdio>/*谁离跟节点近,谁能赢*/
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 100001
int n,m,f[N];
void init()
{
for(int i=1; i<=n; i++)
f[i]=i;
}
int getf(int u,int sum)
{
while(u!=f[u])/*直至到根节点*/
{
sum++;
u=f[u];
}
return sum;
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n+m))/*n为节点数,m为询问数*/
{
init();
int vis=n-1;
while(vis--)
{
int a,b;
scanf("%d%d",&a,&b);
f[b]=a;
}
while(m--)
{
int t1,t2;
scanf("%d%d",&t1,&t2);
if(getf(t1,1)<=getf(t2,1))
printf("lxh\n");
else
printf("pfz\n");
}
}
return 0;
}