\(\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. esp-01和esp-01s烧录固件和程序

    准备工具 USB-TTL 杜邦线若干 esp-01s烧录固件 我烧录的固件是 micropython, 使用的软件是 uPyCraft esp-01s烧录固件接线方法: esp-01s usb-ttl ...

  2. uniCloud云开发入门以及对传统开发方式的思考

    事情缘由 作为选修了移动互联网应用的一员,老师讲的什么JS基础,还有ES6和uniapp,当然是没怎么听,因为是之前大二的时候都大概看过. 但是快到期末,老师讲了云开发,并且布置了与此相关的大作业,自 ...

  3. 这么简单,还不会使用java8 stream流的map()方法吗?

    一.前言 在日常的开发工作中经常碰到要处理list中数据的问题,比如从数据库中查出了很多学生,由于一些原因需要在内存中找出这些学生中的所有姓名,或者把名为"王五"的语文成绩暂时修改 ...

  4. uni 结合vuex 编写动态全局配置变量 this.baseurl

    在日常开发过程,相信大家有遇到过各种需求,而我,在这段事件便遇到了一个,需要通过用户界面配置动态接口,同时,因为是app小程序开发,所以接口中涉及到了http以及websocket两个类型的接口. 同 ...

  5. 【Java SE】课程目录

    〇.课程简介 一.前言入门 二.数据类型.运算符.方法 三.流程控制 四.Idea.方法 五.数组 六.类.对象.封装.构造 七.Scanner类.Random类.ArrayList类 八.Strin ...

  6. git、docker、lunix、python、pycharm等常用命令整理

    git的使用 上传代码git clone ....git branch new_branchgit checkout branch_namegit add .git commit -m "& ...

  7. Ubuntu20.04更换国内镜像源(阿里、网易163、清华、中科大)

    更换方法 Ubuntu采用apt作为软件安装工具,其镜像源列表记录在/etc/apt/source.list文件中. 首先将source.list复制为source.list.bak备份,然后将sou ...

  8. 2022年7月10 第四组 周鹏 CSS的基本认识

    CSS 层叠样式表 网页美观 html相当于原材料,css用来加工好看 如何嵌入? 样式如何显示html元素? 样式通常存储在样式表中 把样式表添加到html元素里 定义CSS方式 1,行内样式,可以 ...

  9. [深度学习] CCPD车牌数据集介绍

    CCPD是一个大型的.多样化的.经过仔细标注的中国城市车牌开源数据集.CCPD数据集主要分为CCPD2019数据集和CCPD2020(CCPD-Green)数据集.CCPD2019数据集车牌类型仅有普 ...

  10. [seaborn] seaborn学习笔记3-直方图Histogramplot

    文章目录 3 直方图Histogramplot 1. 基本直方图的绘制 Basic histogram 2. 数据分布与密度信息显示 Control rug and density on seabor ...