zoukankan      html  css  js  c++  java
  • P 朋友找规律

    题目

    B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的:
    给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1。 在一局游戏开始时,会确定一个节点作为根。接下来从女生开始,双方轮流进行 操作。
    当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然后找出这个点到根节点的简单路径,将路径上所有边的权值翻转(即0变成1,1 变成0 )。
    当一方无法操作时(即所有边的边权均为0),另一方就获得了胜利。
    如果在双方均采用最优策略的情况下,女生会获胜,则输出“Girls win!”,否则输 出“Boys win!”。
    为了让游戏更有趣味性,在每局之间可能会有修改边权的操作,而且每局游戏指 定的根节点也可能是不同的。
    具体来说,修改边权和进行游戏的操作一共有m个,具体如下:
    ∙“0 x”表示询问对于当前的树,如果以x为根节点开始游戏,哪方会获得胜利。
    ∙“1 x y z ”表示将x和y之间的边的边权修改为z。
    B君当然知道怎么做啦!但是他想考考你。

    Input

    包含至多5组测试数据。
    第一行有一个正整数,表示数据的组数。
    接下来每组数据第一行,有二个空格隔开的正整数n,m,分别表示点的个数,操 作个数。保证n,m< 40000。
    接下来n-1行,每行三个整数x,y,z,表示树的一条边。保证1 < x < n, 1 < y < n, 0 <= z <= 1。
    接下来m行,每行一个操作,含义如前所述。保证一定只会出现前文中提到的两 种格式。
    对于操作0,保证1 <= x <= n ;对于操作1,保证1 <= x <= n, 1 <= y <= n, 0 <= z <= 1,保证树上存在一条边连接x和y。

    Output

    对于每组数据的每一个询问操作,输出一行“Boys win!”或者“Girls win!”。

    Sample Input

    2
    2 3
    1 2 0
    0 1
    1 2 1 1
    0 2
    4 11
    1 2 1
    2 3 1
    3 4 0
    0 1
    0 2
    0 3
    0 4
    1 2 1 0
    0 1
    0 2
    0 3
    1 3 4 1
    0 3
    0 4
    

    Sample Output

    Boys win!
    Girls win!
    Girls win!
    Boys win!
    Girls win!
    Boys win!
    Boys win!
    Girls win!
    Girls win!
    Boys win!
    Girls win! 
    Sponsor
    

    题解

    解题思路

    我们可以从一条链的情况来推导
    记录与根节点x相连的边权值为1的数量,如果是偶数则以x为根节点时男孩赢

    代码

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N = 4e4+5;
    struct side {
        int t, d, next;
    }a[N*2];
    int tot, head[N];
    void add(int x, int y, int z) {
        a[++tot].next = head[x];
        head[x] = tot;
        a[tot].t = y;
        a[tot].d = z;
    }
    int n, m, T, s[N];
    int main() {
        scanf("%d", &T);
        while (T--) {
            memset(head, 0, sizeof(head));
            memset(s, 0, sizeof(s));
            tot = 1;
            scanf("%d%d", &n, &m);
            for(int i = 1, x, y, z; i < n; i++) {
                scanf("%d%d%d", &x, &y, &z);
                add(x, y, z); add(y, x, z);
                s[x] += z; s[y] += z;
            }
            while (m--) {
                int x, y, z;
                scanf("%d", &x);
                if (x) {
                    scanf("%d%d%d", &x, &y, &z);
                    int k;
                    for(int i = head[x]; i; i = a[i].next)
                        if (a[i].t == y) {
                            k = i;
                            break;
                        }
                    if(a[k].d != z) {
                        a[k].d = z;
                        if(z) s[x] += 1, s[y] += 1;
                        else s[x] -= 1, s[y] -=1;
                        a[k^1].d = z;
                        //反向边也要改变 注意tot初始值为奇数才可以这样用
                    }
                }
                else {
                    scanf("%d", &x);
                    if (s[x] % 2) puts("Girls win!");
                    else puts("Boys win!");
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    CF 142B Tprimes
    CF 231A Team
    poj 2001 Shortest Prefixes ——字典树入门
    hdu 1039 Easier Done Than Said?
    poj 2528 Mayor's posters
    hdu 1061 Rightmost Digit
    poj 2503 Babelfish
    CF271 A. Beautiful Year
    poj 2752
    CF271 B. Prime Matrix
  • 原文地址:https://www.cnblogs.com/shawk/p/12686871.html
Copyright © 2011-2022 走看看