cdoj32-树上战争(Battle on the tree) 【记忆化搜索】

http://acm.uestc.edu.cn/#/problem/show/32

树上战争(Battle on the tree)

Time Limit: 12000/4000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

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

Input

输入包含多组数据

每组第一行包含两个数N,M(N,M100000),N表示树的节点数,M表示询问数,N=M=0表示输入结束。节点的编号为1N

接下来N1行,每行2个整数A,B(1A,BN),表示编号为A的节点是编号为B的节点的父亲。

接下来M行,每行有2个数,表示lxhpfz的初始位置的编号X,Y(1X,YN,XY),lxh总是先移动。

Output

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

Sample input and output

Sample Input Sample Output
2 1

1 2

1 2

5 2

1 2

1 3

3 4

3 5

4 2

4 5

0 0
lxh

pfz

lxh

 

 

题解:记忆化搜索。这道题目,其实是要你求出两人所在节点的深度(即到根的距离),做个比较即可。实现时,把儿子指向父亲作为有向边,因为是树,所以n-1个节点对应n-1条有向边。做个记忆化搜索即可。

代码:

 1 #include <fstream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <iostream>

 5 

 6 using namespace std;

 7 

 8 const int N=100005;

 9 int n,m;

10 int u[N];

11 int dis[N];

12 bool b[N];

13 

14 int dfs(int i);

15 

16 int main()

17 {

18     //freopen("D:\\input.in","r",stdin);

19     //freopen("D:\\output.out","w",stdout);

20     int t1,t2;

21     while(scanf("%d%d",&n,&m),n){

22         memset(dis,-1,sizeof(dis));

23         memset(b,0,sizeof(b));

24         for(int i=1;i<n;i++){

25             scanf("%d%d",&t1,&t2);

26             u[t2]=t1;//由儿子指向父亲

27             b[t2]=1;

28         }

29         for(int i=0;i<m;i++){

30             scanf("%d%d",&t1,&t2);

31             if(dis[t1]==-1)   dfs(t1);

32             if(dis[t2]==-1)   dfs(t2);

33             if(dis[t1]<=dis[t2])    puts("lxh");

34             else    puts("pfz");

35         }

36     }

37     return 0;

38 }

39 int dfs(int i){

40     if(dis[i]!=-1)  return dis[i];

41     if(b[i]==0) return 0;

42     dis[i]=dfs(u[i])+1;

43     return dis[i];

44 }

你可能感兴趣的:(tree)