C - 朋友 HDU - 5963

 链接:https://vjudge.net/contest/400079#problem/C

思路:

以某个结点作为根进行博弈的时候,无论翻转哪个结点,与根结点相连的边值是一定会翻转。所以只要考虑与根相连的结点话,两人的最优策略就出来了:若对方翻转后使一个与根结点相连的结点p与其之间边L的权值变为1,那自己就翻转以p为祖先的结点使得该条边L变回原状态(一定有这样的点,最差的情况就是翻转p)。对于与根相连的边来说,每次对手这样翻转你就一定能还原对方的操作。若对方翻转后使一个与根结点相连的结点p与其之间边L的权值变为0,或你不能再对L操作,或你也可以模仿对方的操作,但就如上所说,对方一定能还原你的操作。因此操作翻转了初始状态就为1的与跟相连的边L的操作最终不会被还原,是有效的,翻转初始状态为0的边L是无效的。所以初始与根相连的边权值为1的边的个数决定了输赢。若为偶数个,则后手胜,奇数个则先手胜。
  因此只要统计与每个点连接的边的个数的奇偶性就能得出胜负。
  代码如下;
 1 #include <iostream> 
 2 #include <cmath>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 using namespace std; 
 9 #define ll long long int 
10 const int maxn=1e5;
11 int nod[40005];//nod[i]记录与点i相连的权值为1的边的数量
12 map<int,int> tree;
13 int main()  
14 {    
15     int T;
16     int n,m;
17     scanf("%d",&T);
18     while(T--)
19     {
20         tree.clear();
21         memset(nod,0,sizeof(nod));
22         scanf("%d%d",&n,&m);
23         for(int i=1;i<n;i++){
24             int x,y,z;
25             scanf("%d%d%d",&x,&y,&z);
26             if(z==1){
27                 nod[x]++;
28                 nod[y]++;
29                 tree[x*maxn+y]=1;//记录下两个点之间边的值
30                 tree[y*maxn+x]=1;
31             }
32         }
33         while(m--)
34         {
35             int k;
36             scanf("%d",&k);
37             if(k==1){
38                 int x,y,z;
39                 scanf("%d%d%d",&x,&y,&z);
40                 if(z==1&&tree[x*maxn+y]==0)//如果原来两个点之间的边的值为0
41                 {
42                     nod[x]++;
43                     nod[y]++;
44                     tree[x*maxn+y]=tree[y*maxn+x]=1;
45 
46                 }
47                 if(z==0&&tree[x*maxn+y]==1)//如果原来两个点之间的边的值为1
48                 {
49                     nod[x]--;
50                     nod[y]--;
51                     tree[x*maxn+y]=tree[y*maxn+x]=0;
52                 }
53             }
54             else if(k==0)
55             {
56                 int x;
57                 scanf("%d",&x);
58                 if(nod[x]&1)
59                     printf("Girls win!\n");
60                 else    
61                     printf("Boys win!\n");
62             }   
63         }        
64     }
65     return 0;  
66 }  
View Code

 

posted @ 2020-10-10 17:17  古比  阅读(83)  评论(0编辑  收藏  举报