[CF868E]Policeman and a Tree
题目大意:有一棵$n$个点的带边权的树,上面有$m$个罪犯,速度为任意大,有一个警察在点$S$,速度为$1$。若警察和罪犯在同一个地方,罪犯就被干掉了,警察希望干掉所有罪犯时间最短,而罪犯希望最大化这个时间。求出这个时间,若无解输出 Terrorists win 。$n,m\leqslant 50$
题解:一定有解,令$f[u][v][x][y]$表示从警察$u$走到$v$,$v$关于$u$的子树内有$x$个罪犯,另外的节点还有$y$个罪犯的最小时间。警察一定选择$dp$值最小的走,而罪犯的分布会使每条边$dp$值得最小值最大。用类似背包的东西转移。在转移时另开一个数组$g[i][j]$表示现在是$v$的第$i$棵子树,放了$j$个罪犯所需的时间。
$$
g[i][j]=\max\{g[i][j],\min\{g[i-1][j-k],dp[v][v'][k][x+y-k]+w\}\}
$$
$v'$为$v$的第$i$棵子树,$k$为$v'$这棵子树放几个罪犯,$w$为$v\to v'$的边权。$g$明显可以用$01$背包的方法把第一维滚掉。到叶子的时候抓住罪犯然后返回。记忆化搜索即可。
卡点:无
C++ Code:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
const int maxn = 60, inf = 0x3f3f3f3f; int head[maxn], cnt = 1, deg[maxn];
struct Edge {
int to, nxt, w;
} e[maxn << 1];
inline void addedge(int a, int b, int c) {
e[++cnt] = (Edge) { b, head[a], c }; head[a] = cnt;
e[++cnt] = (Edge) { a, head[b], c }; head[b] = cnt;
++deg[a], ++deg[b];
} int n, m, S, sz[maxn];
int f[maxn << 1][maxn][maxn];
void dfs(int u, int fa = 0) {
for (int i = head[u], v; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa) dfs(v, u), sz[u] += sz[v];
}
}
int dp(int E, int x, int y) {
if (!x && !y) return 0;
int &F = f[E][x][y], u = e[E].to;
if (~F) return F;
if (deg[u] == 1) {
if (y == 0) return 0;
return F = dp(E ^ 1, y, 0) + e[E].w;
}
int g[maxn];
memset(g, 0, sizeof g), g[0] = inf;
for (int i = head[u], v; i; i = e[i].nxt) if (i ^ E ^ 1) {
v = e[i].to;
for (int j = x; j; --j)
for (int k = j; k; --k)
g[j] = std::max(g[j], std::min(g[j - k], dp(i, k, x + y - k) + e[i].w));
}
return F = g[x];
} int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
std::cin >> n;
for (int i = 1, a, b, c; i < n; ++i) {
std::cin >> a >> b >> c;
addedge(a, b, c);
}
std::cin >> S >> m;
for (int i = 0, x; i < m; ++i) std::cin >> x, ++sz[x];
dfs(S), memset(f, -1, sizeof f);
int ans = inf;
for (int i = head[S], v; i; i = e[i].nxt) {
v = e[i].to;
ans = std::min(ans, dp(i, sz[v], m - sz[v]) + e[i].w);
}
std::cout << ans << '\n';
return 0;
}
[CF868E]Policeman and a Tree的更多相关文章
- Codeforces 868E Policeman and a Tree
题意简述 给你一颗有n个点的树,每条边有边权,有一个警察一开始在点S,他的速度是1,即通过一条长度为x的边要花x单位时间. 有m个罪犯,一开始第i个在点x[i],他们的速度无限快. 如果罪犯和警察到达 ...
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
随机推荐
- Kafka 消费者到底是什么 以及消费者位移主题到底是什么(Python 客户端 1.01 broker)
Kafka 中有这样一个概念消费者组,所有我们去订阅 topic 和 topic 交互的一些操作我们都是通过消费者组去交互的. 在 consumer 端设置了消费者的名字之后,该客户端可以对多个 to ...
- react的3种组件
推荐阅读:https://www.jianshu.com/p/2726b8654989 1. createClass 已不推荐使用,这里不再多讲.但你仍需要了解它,因为你可能会接触到一些旧项目,或者一 ...
- GitHub如何删除一个代码仓库
进入GitHub之后,点击“your repositories”查看所有的代码仓库. 在代码仓库中选择一个需要删除的,进入其详情页 在详情页中找到“setting”设置,下拉至最后可以看到删除选项. ...
- 【CSP模拟赛】starway(玄学建边 最小生成树)
问題描述 小w伤心的走上了 Star way to heaven. 到天堂的道路是一个笛卡尔坐标系上一个n×m的长方形通道(顶点在(0,0))和(n,m)),小w从最左边任意一点进入,从右边任意一 ...
- jmap -heap 查看堆内存
概述 用jmap -heap命令可以查看linux堆内存分布 具体用法 1:先查出tomcat的进程号 例如: 然后执行 jmap -heap 7095 可以打印出整体的堆信息 可以看到经过分配的 ...
- [转]npm安装教程
原文地址:https://www.cnblogs.com/lgx5/p/10732016.html 一.使用之前,我们先来掌握3个东西是用来干什么的. npm: Nodejs下的包管理器. webpa ...
- Swift编程语言中如何实现自定义类型的for-in循环(基于Swift 2.2)
我们在Swift编程语言中常常会用到for-in循环(在编程语言术语中又被称为for-each).此外,从Swift 2.2版本起,for循环将只支持for-in形式,而不支持for i = 0; i ...
- (转)scipy详解
原文:https://www.cnblogs.com/ws0751/p/8361353.html#top 登月图片消噪 scipy.fftpack模块用来计算快速傅里叶变换速度比传统傅里叶变换更快 ...
- Sublime用正则表达式进行逗号分隔实现列的替换
eg: ([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*).* 这是取前面10列,后面的不管 ...
- linux信号--阻塞与未决
执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending). 进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程解 ...