• [HDU


    [HDU - 5963 ]朋友 (树上博弈,思维)

    题目链接: HDU - 5963

    题面:

    思路:

    我们通过推理应该知道如下性质:

    • 对于根节点的每一个子树,操作上互不干扰。而且玩家的任何操作没有技巧性,即两人随便操作不影响最终的赢家。

    • 对于根节点每一个边权为1的儿子,想将该整个子树完全变为0,需要做奇数次操作。

    那么我们只需要维护出每一个节点边权为1的出边个数即可,偶数个boys 赢,奇数个girls赢。

    关于第二个性质的证明:

    • 当整个子树为一条链,那么链中连续的0和1可以缩为一个,那么链条一定为以1为起点以1为结尾的交叉序列,显然长度一定为奇数。而玩家每一次翻转操作只会减短一个序列元素,所以需要奇数次操作。
    • 当子树中某个节点(now)有多个儿子时,先只考虑一个儿子,则为链的情况,需要奇数次操作。根节点到节点(now)路径中边都变为0,那么该节点的其他儿子与根节点形成的链都是为以0为起点以1为结尾的交叉序列,显然长度一定为偶数。最终还是需要奇数次操作。

    代码:

    #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;
    }
    
  • 相关阅读:
    对Java总体上的认识
    HTML+CSS学习情况
    读过的书籍
    FSCapture[个人认为最好的截图工具]
    会使用的软件
    深入理解Java中的引用的含义与原理
    从头开始学JavaScript (三)——数据类型
    从头开始学JavaScript (二)——变量及其作用域
    从头开始学JavaScript(一)——基础中的基础
    【Head First Javascript】学习笔记0——自己制作chm参考手册素材
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/14022042.html
Copyright © 2020-2023  润新知