[HDU - 5963 ]朋友 (樹上博弈,思維)

[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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章