2024牛客暑期多校训练营6 A-Cake

题目描述

Grammy and Oscar bought a big cake. They like it very much, so dividing the cake becomes difficult. In order to divide the cake in a relatively fair way, they decided to play a game to earn more part of the cake for themselves.

The game consists of two phases.

For phase 1, Grammy and Oscar will play on a tree rooted at vertex 1. Each edge of the tree has a number 0 or 1. Initially, there is a horse on the root.
They take turns moving the horse, with Grammy moving first. At each turn, suppose the horse is at vertex ppp, the player must select some child of ppp and move the horse to that child of ppp. Phase 1 ends when ppp has no children. As a result of phase 1, we will get a string S formed by concatenating the numbers on edges the horse has passed by. Note that S consists of only 0 and 1.

For phase 2, Grammy and Oscar will play on the string S they obtained in phase 1. Let mmm be the length of S. Firstly, Oscar will divide the cake into mmm parts (some parts can be empty). Then mmm steps follow. At the iii-th step, if the iii-th character of S is 1, Grammy will choose one part and get it; otherwise, Oscar will choose one part and get it.

Both of them hope to maximize the cake they get, and they both play optimally. Please calculate the fraction of cake Grammy gets.

输入描述:

There are multiple test cases. The first line of the input contains an integer TTT (1≤T≤100 0001\leq T\leq 100\,0001≤T≤100000) indicating the number of test cases. For each test case:

The first line contains one integer nnn (2≤n≤200 0002\leq n\leq 200\,0002≤n≤200000), indicating the size of the rooted tree in phase 111.

For the following n−1n-1n−1 lines, the iii-th line contains three integers x,y,kx, y, kx,y,k (1≤x,y≤n,0≤k≤11\leq x,y\leq n, 0\leq k\leq 11≤x,y≤n,0≤k≤1) describing an edge connecting xxx and yyy with number kkk.

It is guaranteed that the sum of nnn over all test cases will not exceed 2e5

输出描述:

For each test case:

Output one line containing one real number indicating the fraction of cake Grammy gets in the game, assuming both players play optimally.

Your answer is considered correct if its absolute or relative error does not exceed 10−910^{-9}10−9.

Formally, let your answer be aaa, and the jury's answer be bbb. Your answer is accepted if and only if ∣a−b∣max(1,∣b∣)≤10−9\frac{|a-b|}{max(1,|b|)}\leq 10^{-9}max(1,∣b∣)∣a−b∣​≤10−9.

输入

3
3
1 2 1
1 3 0
4
1 2 0
1 3 1
3 4 0
5
1 2 0
1 3 0
3 4 1
4 5 1

输出

1.000000000000
0.500000000000
0.000000000000

题意就是,阶段一,给了一棵树边权由1和0组成,两人从树的根节点1由Grammy开始轮流走走到叶子节点停,经过的每条边的边权组成一个01串s;

阶段二,设s长度为m, 由Oscar将蛋糕分成m份(可以为空),字符串从头开始按顺序,1时Grammy取一块蛋糕,0时Oscar取一块蛋糕。

两人都走最优策略,问Grammy最后取到整个蛋糕的几分之几。

先看二阶段,因为是Oscar分蛋糕,可以为空,所以对于Oscar来说要找一个0占比最多(1占比最少)的前缀,长为l,然后将蛋糕均分为l块,(如果不均分的话先拿的人会拿走最大的那块)。

所以对于一阶段,Grammy希望走过1占比更多的字串,Oscar希望走过0占比更多的字串,树型dp可以得到经过这个节点Grammy的分数,但考虑2阶段Oscar会选一个1占比最少的前缀,所以还要取最小的分数,叶子节点不管。

#include<bits/stdc++.h>
// #define int long long

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
const int N=200010;
int n, m;
vector<PII> v[N];
double d[N];

void dfs(int u, int pre, int dep, int num1, int t) {
    if(u != 1) d[u] = 1.0 * num1 / dep;//以当前节点为止的01串作为前缀可得的分数
    double k = 1 - t;
    int f = 0;//判断是否是叶子节点
    for(auto p : v[u]) {
        int j = p.first, c = p.second;
        if(j == pre) continue ;
        f ++;
        dfs(j, u, dep + 1, num1 + c, t ^ 1);
        //k表示两人经过u后按最优策略走之后可以得到的分数
        if(t) k = max(k, d[j]);//Grammy的回合会选前缀1最多(分数最大的)的情况
        else k = min(k, d[j]);//Oscar相反
    }

    if(u == 1) {
        d[u] = k;
        return ;
    }

    
    //对于二阶段,Oscar会选择1最少的前缀,还要比较当前节点为止的01串作为前缀的分数取最小的
    if(f) d[u] = min(k, d[u]);//叶子节点不管
}


signed main() {
    // ios::sync_with_stdio(false);
    int cas;
    scanf("%d", &cas);
    while(cas --) {
        scanf("%d", &n);
        for(int i = 1;i <= n;i ++) v[i].clear();
        for(int i = 1;i < n;i ++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            v[a].push_back({b, c});
            v[b].push_back({a, c});
        }
        dfs(1, 1, 0, 0, 1);

        printf("%.10f\n", d[1]);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值