[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 ...
随机推荐
- LeetCode 3Sum Closest 最近似的3sum(2sum方法)
题意:找到最接近target的3个元素之和,并返回该和. 思路:用2个指针,时间复杂度O(n^2). int threeSumClosest(vector<int>& nums, ...
- iOS上架问题解决
dns问题 http://iphone.91.com/tutorial/syjc/140509/21686339.html 网络问题 手机4g开wifi,上传提交多次 时间问题 东八区下午6点上架成功 ...
- KTU Programming Camp (Winter Training Day 1)
A.B.C(By musashiheart) 0216个人赛前三道题解 E(By ggg) Gym - 100735E Restore H(by pipixia) Gym - 100735H
- Heacher互助平台 α版本冲刺
课程属性 作业课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/ 作业链接 https://edu.cnblogs.co ...
- hydra 中文文档
hydra(九头蛇)是一款开源的协议爆破工具,功能十分强大!!! 具体使用如下: -R 继续从上一次进度接着破解 -I 忽略已破解的文件进行破解 -S 采用SSL链接 -s 端口 指定非默认服务端 ...
- 自写小函数处理 javascript 0.3*0.2 浮点类型相乘问题
const reg = /^([-+]?)([0-9]+)\.([0-9]*)$/; // 判断是不是浮点数 const isFloat = function(number){ return reg. ...
- [POJ] 2411 Mondriaan's Dream
Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 18903 Accepted: 10779 D ...
- python 连接redis cluster
#!/usr/bin/env python # encoding: utf-8 #@author: 东哥加油! #@file: clear_pool.py #@time: 2018/8/28 17:0 ...
- GIMP中的新建Layer与更改Layer大小
这边可以直接New Layer,新建一个Layer,还可以New from Visible,第二种是将当前的状态下图像复制出来. 改变Layer的大小,一般的方法两种: Crop to Selecti ...
- react 列表渲染
https://reactjs.org/docs/lists-and-keys.html#keys 以下代码运行会报错:Warning: Each child in an array or itera ...