[luoguP2495] [SDOI2011]消耗战(DP + 虚树)
明显虚树。
别的题解里都是这样说的。
先不考虑虚树,假设只有一组询问,该如何dp?
f[u]表示把子树u中所有的有资源的节点都切掉的最优解
如果节点u需要切掉了话,$f[u]=val[u]$
否则如果u的子树中有需要切除的点的话,$f[u] = min(val[u], \sum\limits_{v是u的儿子}f[v])$
val[u]表示是根到u的路径上最小的边的权值。
最后转移到虚树上即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1000000
#define LL long long using namespace std; int n, m, cnt, rp, top, T;
int head[N], to[N], nex[N], dfn[N], f[N][21], q[N], deep[N], s[N];
LL ans[N], dp[N], val[N];
bool flag[N]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline void add(int x, int y, int z)
{
to[cnt] = y;
val[cnt] = z;
nex[cnt] = head[x];
head[x] = cnt++;
} inline void dfs1(int u)
{
int i, v;
dfn[u] = ++rp;
deep[u] = deep[f[u][0]] + 1;
for(i = 0; f[u][i]; i++) f[u][i + 1] = f[f[u][i]][i];
for(i = head[u]; ~i; i = nex[i])
{
v = to[i];
if(!dfn[v])
{
f[v][0] = u;
dp[v] = min(dp[u], val[i]);
dfs1(v);
}
}
head[u] = -1;
} inline int calc_lca(int x, int y)
{
int i, j;
if(deep[x] < deep[y]) swap(x, y);
for(i = 20; i >= 0; i--)
if(deep[f[x][i]] >= deep[y]) x = f[x][i];
if(x == y) return x;
for(i = 20; i >= 0; i--)
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
} inline bool cmp(int x, int y)
{
return dfn[x] < dfn[y];
} inline void dfs2(int u)
{
LL sum = 0;
int i, v;
ans[u] = dp[u];
for(i = head[u]; ~i; i = nex[i])
{
v = to[i];
dfs2(v);
sum += ans[v];
}
if(sum && !flag[u]) ans[u] = min(ans[u], sum);
head[u] = -1;
} inline void solve()
{
int i, lca;
m = read();
top = cnt = 0;
for(i = 1; i <= m; i++) q[i] = read(), flag[q[i]] = 1;
sort(q + 1, q + m + 1, cmp);
for(i = 1; i <= m; i++)
{
if(!top)
{
s[++top] = q[i];
continue;
}
lca = calc_lca(q[i], s[top]);
while(dfn[lca] < dfn[s[top]])
{
if(dfn[lca] >= dfn[s[top - 1]])
{
add(lca, s[top], 0);
if(s[--top] != lca) s[++top] = lca;
break;
}
add(s[top - 1], s[top], 0), top--;
}
s[++top] = q[i];
}
while(top > 1) add(s[top - 1], s[top], 0), top--;
dfs2(s[1]);
printf("%lld\n", ans[s[1]]);
for(i = 1; i <= m; i++) flag[q[i]] = 0;
} int main()
{
int i, x, y, z;
n = read();
memset(head, -1, sizeof(head));
for(i = 1; i < n; i++)
{
x = read();
y = read();
z = read();
add(x, y, z);
add(y, x, z);
}
dp[1] = 1ll * 1e9 * 1e9;
dfs1(1);
T = read();
while(T--) solve();
return 0;
}
[luoguP2495] [SDOI2011]消耗战(DP + 虚树)的更多相关文章
- BZOJ 2286: [Sdoi2011消耗战 [DP 虚树]
传送门 题意: 删除价值和最小的边使得$1$号点与$k$个关键点不连通 一个树形DP...但是询问多次,保证总的关键点数为$O(n)$ 先说一下这个$DP$ $f[i]$表示子树$i$中的关键点与$1 ...
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- [SDOI2011]消耗战(虚树)
洛古题面 题意:给定一棵树,割断每一条边都有代价,每次询问会给定一些点,求用最少的代价使所有给定点都和1号节点不连通 暴力\(DP\) 我们先考虑暴力怎么做 设\(dp[u]\)为以\(u\)为根的子 ...
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4261 Solved: 1552 [Submit][Sta ...
- 洛谷P2495 [SDOI2011]消耗战(虚树dp)
P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...
- bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...
- 2018.09.25 bzoj2286: [Sdoi2011]消耗战(虚树+树形dp)
传送门 又一道虚树入门题. 这个dp更简单啊. 直接记录每个点到1的距离,简单转移就行了. 代码: #include<bits/stdc++.h> #define N 250005 #de ...
- BZOJ 2286 [Sdoi2011]消耗战(虚树+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题目大意] 出一棵边权树,每次给出一些关键点,求最小边割集, 使得1点与各个关 ...
- 洛谷 P2495 [SDOI2011]消耗战(虚树,dp)
题面 洛谷 题解 虚树+dp 关于虚树 了解一下 具体实现 inline void insert(int x) { if (top == 1) {s[++top] = x; return ;} int ...
- [Bzoj2286][Sdoi2011]消耗战(虚树模板题附讲解)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4896 Solved: 1824[Submit][Statu ...
随机推荐
- linux_base-f10-10_7 linuxulator is not (kld)loaded
# cd linux_base-f10/# make install clean===> linux_base-f10-10_7 linuxulator is not (kld)loaded. ...
- iis的网站发布
1.打开IIS服务器,添加“新网站”,命名网站的名称.物理路径(存放index.aspx的文件路径).ip地址和端口:2.在已经添加的网站,启用“目录浏览”,“默认文档”设置将要打开的网页 注:(1) ...
- jmeter分布式测试配置
jmeter分布式测试 说明:1台8核16G的windows2008的机器,只能器6000个线程,否则效果不是很好:并且负载机器需要做如下设置: 1.打开注册表:regedit 2.HKEY_LOCA ...
- 操作系统项目:向Linux内核添加一个系统调用
内容: 向Linux增加一个系统调用 撰写一个应用测试程序调用该系统调用 使用ptrace或类似的工具对该测试程序进行跟踪调 环境: 1.vmware workstation 15.0.0 2.ubu ...
- Koa -- 基于 Node.js 平台的下一代 web 开发框架 koa.bootcss.com
Koa -- 基于 Node.js 平台的下一代 web 开发框架 koa.bootcss.com
- CPP-基础:TCHAR
目 录 定义 使用原理 1.定义 TCHAR是通过define定义的字符串宏[1] 2.使用原理 因为C++支持两种字符串,即常规的ANSI编码(使用""包裹)和Unicode编码 ...
- 使用Fiddler抓取Android模拟器中的Android_APP请求
对Fiddler的设置:在https://www.telerik.com/download/fiddler网站上下载Fiddler,输入内容后点击下面按钮进行下载: 下载成功后,打开Fiddler进行 ...
- $monitor用法
1.$monitor 进程同一时间有且仅有一个,若多次调用$monitor,新进程会代替以前的monitor进程. 2.$fmonitor可以同时存在任意个. 3.一般不用$monitor系统函数. ...
- 【windows】【php】【nginx】windows 开机自启动nginx php 及nginx php配置
#启动php-nginx start-php-nginx.bat @ECHO OFFECHO Starting PHP FastCGI...RunHiddenConsole.exe php-c ...
- Python基本运算符和流程控制
常量 常量即不可改变的量,在Python中不存在常量,我们只能逻辑上规定一个常量并不去修改它,通常用全大写字母表示. 基本运算符之二 算术运算 运算符 说明 ** 幂运算 *, /, //, % 乘. ...