题目链接: HDU - 5963
我们通过推理应该知道如下性质:
对于根节点的每一个子树,操作上互不干扰。而且玩家的任何操作没有技巧性,即两人随便操作不影响最终的赢家。
对于根节点每一个边权为1的儿子,想将该整个子树完全变为0,需要做奇数次操作。
那么我们只需要维护出每一个节点边权为1的出边个数即可,偶数个boys 赢,奇数个girls赢。
关于第二个性质的证明:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn=40000+10;
#define mp make_pair
int n,m;
set<pii> st[maxn];
int info[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(int i=2;i<=n;++i)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
st[x].insert(mp(y,z));
st[y].insert(mp(x,z));
if(!z)
continue;
info[x]++;
info[y]++;
}
while(m--)
{
int op,x,y,z;
scanf("%d",&op);
if(op==0)
{
scanf("%d",&x);
int ans=info[x];
if(ans&1)
{
puts("Girls win!");
}else
{
puts("Boys win!");
}
}else
{
scanf("%d %d %d",&x,&y,&z);
if(st[x].count(mp(y,z))==1)
{
continue;
}else
{
if(z==0)
{
info[x]--;info[y]--;
}else
{
info[x]++;info[y]++;
}
st[x].erase(st[x].lower_bound(mp(y,!z)));
st[y].erase(st[y].lower_bound(mp(x,!z)));
st[x].insert(mp(y,z));
st[y].insert(mp(x,z));
}
}
}
for(int i=1;i<=n;++i)
{
st[i].clear();
info[i]=0;
}
}
return 0;
}
原文:https://www.cnblogs.com/qieqiemin/p/14022042.html