\(\text{Problem}\)

A君和B君在玩一种叫做新红黑树的游戏,即在一棵由红枝和黑枝构成的树上轮流砍树枝,每次砍一枝,A君每次只能砍红枝,B君每次只能砍黑枝,当其中某人已经没有树枝砍的时候,由另外一人砍,直到砍完全部树枝。树枝是带权的,每个人的总分是他砍的树枝的权值之和,那些由于其他树枝被砍掉而与根失去联系的树枝会自动消失。每次由A君先砍,设“D=A君的得分-B君的得分”,A君想让D最大,而B君想让D最小,A君和B君都是极其聪明的人,他们始终以最优策略进行整个游戏,你知道最后的D值是多少吗?

\(1\le n\le 20\)

\(\text{Solution}\)

考虑两个 \(dfs\) 互相暴搜,二进制记录边信息

然后记忆化

以前没打过,今天考场一遍过了?!

比较慢,其实可以预处理删边后同时影响的边的二进制信息

这样就不需要每次删边后再一条一条边的删去子树影响

\(\text{Code}\)

#include <cstdio>
#include <cstring>
#include <vector>
#define RE register
using namespace std; const int N = 25, INF = 2e9;
int n, f[1<<21][2], dep[N];
struct edge{int u, v, c, w;}e[N];
vector<int> g[N]; void prepare(int x, int fa)
{
dep[x] = dep[fa] + 1;
for(RE int i = 0; i < n - 1; i++)
{
if (e[i].u == x && e[i].v ^ fa)
{
prepare(e[i].v, x), g[x].push_back(i);
for(RE int j = 0; j < g[e[i].v].size(); j++) g[x].push_back(g[e[i].v][j]);
}
else if (e[i].v == x && e[i].u ^ fa)
{
prepare(e[i].u, x), g[x].push_back(i);
for(RE int j = 0; j < g[e[i].u].size(); j++) g[x].push_back(g[e[i].u][j]);
}
}
} int dfs1(int s);
int dfs2(int s);
int dfs1(int s)
{
if (f[s][0] != -INF) return f[s][0];
if (s == (1 << n - 1) - 1) return 0;
int ret = -INF, bz = 0;
for(RE int i = 0; i < n - 1; i++)
{
if (((s >> i) & 1) || (e[i].c != 1)) continue;
int ss = (s | (1 << i)), x = e[i].u, y = e[i].v;
if (dep[x] < dep[y]) swap(x, y);
for(RE int j = 0; j < g[x].size(); j++) ss |= (1 << g[x][j]);
ret = max(ret, e[i].w - dfs2(ss)), bz = 1;
}
if (!bz) return -dfs2(s);
return f[s][0] = ret;
}
int dfs2(int s)
{
if (f[s][1] != -INF) return f[s][1];
if (s == (1 << n - 1) - 1) return 0;
int ret = -INF, bz = 0;
for(RE int i = 0; i < n - 1; i++)
{
if (((s >> i) & 1) || (e[i].c != -1)) continue;
int ss = (s | (1 << i)), x = e[i].u, y = e[i].v;
if (dep[x] < dep[y]) swap(x, y);
for(RE int j = 0; j < g[x].size(); j++) ss |= (1 << g[x][j]);
ret = max(ret, e[i].w - dfs1(ss)), bz = 1;
}
if (!bz) return -dfs1(s);
return f[s][1] = ret;
} int main()
{
scanf("%d", &n), ++n;
for(RE int i = 0; i < n - 1; i++)
scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].c, &e[i].w), ++e[i].u, ++e[i].v;
prepare(1, 0);
for(RE int i = 0; i < (1 << n - 1); i++) f[i][0] = f[i][1] = -INF;
printf("%d\n", dfs1(0));
}

JZOJ 1075. 【GDKOI2006】新红黑树的更多相关文章

  1. 二叉搜索树、AVL平衡二叉搜索树、红黑树、多路查找树

    1.二叉搜索树 1.1定义 是一棵二叉树,每个节点一定大于等于其左子树中每一个节点,小于等于其右子树每一个节点 1.2插入节点 从根节点开始向下找到合适的位置插入成为叶子结点即可:在向下遍历时,如果要 ...

  2. 红黑树(R-B Tree)

    R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). ...

  3. Linux CFS调度器之pick_next_task_fair选择下一个被调度的进程--Linux进程的管理与调度(二十八)

    1. CFS如何选择最合适的进程 每个调度器类sched_class都必须提供一个pick_next_task函数用以在就绪队列中选择一个最优的进程来等待调度, 而我们的CFS调度器类中, 选择下一个 ...

  4. Linux进程调度策略的发展和演变--Linux进程的管理与调度(十六)

    1 前言 1.1 进程调度 内存中保存了对每个进程的唯一描述, 并通过若干结构与其他进程连接起来. 调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个 ...

  5. Linux进程调度与抢占

    一.linux内核抢占介绍 1.抢占发生的必要条件 a.preempt_count抢占计数必须为0,不为0说明其它地方调用了禁止抢占的函数,比如spin_lock系列函数.b.中断必须是使能的状态,因 ...

  6. Java 容器 LinkedHashMap源码分析2

    一.类签名 LinkedHashMap<K,V>继承自HashMap<K,V>,可知存入的节点key永远是唯一的.可以通过Android的LruCache了解LinkedHas ...

  7. Linux进程调度策略的发展和演变(转)

    转发:http://blog.csdn.net/gatieme/article/details/51701149  1 前言 1.1 进程调度 内存中保存了对每个进程的唯一描述, 并通过若干结构与其他 ...

  8. Linux 调度器发展简述

    引言 进程调度是操作系统的核心功能.调度器只是是调度过程中的一部分,进程调度是非常复杂的过程,需要多个系统协同工作完成.本文所关注的仅为调度器,它的主要工作是在所有 RUNNING 进程中选择最合适的 ...

  9. sicily 题目分类

    为了方便刷题,直接把分类保存下来方便来找. 转自:http://dengbaoleng.iteye.com/blog/1505083 [数据结构/图论] 1310Right-HeavyTree笛卡尔树 ...

  10. linux内核中的数据结构

    http://vinllen.com/linuxnei-he-zhong-de-shu-ju-jie-gou/ https://zhuanlan.zhihu.com/p/58087261 https: ...

随机推荐

  1. 二分查找-LeetCode704 简单题

    LeetCode代码链接:https://leetcode.cn/problems/binary-search/ 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ...

  2. Day36:List详解

    List 1.1 概述 List为Collection的子接口,代表的一组任意对象,有序,有下标.元素可以重复. 1.2 方法 方法名 说明 void add(int index,Object o) ...

  3. C++面向对象程序设计期末复习笔记[吉林大学](结合历年题速成85)

    1.头文件 头文件的作用就是被其他的.cpp包含进去的.它们本身并不参与编译,但实际上,它们的内容却在多个.cpp文件中得到了编译.根据"定义只能一次"原则我们知道,头文件中不能放 ...

  4. 组件封装----useImperativeHandle和ref

    useImperativeHandle(ref, createHandle, [deps]) 作用: 减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法 参数1: 父组件传递的 ...

  5. 9、IDEA回退Git版本

    转载自 在工作中有时候会要求我们将以前提交的代码新开一个分支,而把之前提交的分支回退到以前某个版本. 1.通过IDEA查看Git历史记录,复制当前版本号. 2.记录当前版本号后,再复制你要回退的版本号 ...

  6. [深度学习] tf.keras入门5-模型保存和载入

    目录 设置 基于checkpoints的模型保存 通过ModelCheckpoint模块来自动保存数据 手动保存权重 整个模型保存 总体代码 模型可以在训练中或者训练完成后保存.具体文档参考:http ...

  7. iOS开发小结 - 通过PUT请求上传数据

    一般服务器上传数据一般都是用POST请求,这样通过AFNetworking的POST请求稳稳的,但是有一天遇到一个问题,服务器上传数据用的是PUT请求,发现用AFNetworking并不是那么好用,今 ...

  8. Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round) A-D

    比赛链接 A 题意 设计一条线路要贴着6个墙面走,从 \((a,b)\) 到 \((f,g)\) ,线路长度最短. 题解 知识点:模拟. 分类取最短即可. 时间复杂度 \(O(1)\) 空间复杂度 \ ...

  9. [阿里云]Datahub测试使用记录

    由于需要测试阿里云Datahub功能,因此测了一下Datahub的一些功能 DATAHUB: 简介: 阿里云的流式数据(streaming)处理平台 对流式数据的发布(publish)订阅(subsc ...

  10. STM32F103和AIR32F103的FreeRTOS中断优先级

    关于 Arm Cortex M 系列内核的中断优先级 https://community.arm.com/arm-community-blogs/b/embedded-blog/posts/cutti ...