[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 ...
随机推荐
- window服务的使用
目前的项目中使用很多服务来进行实现.服务是依靠windows操作系统来实现.可以是定时器类型,比如定时执行费时的任务,这种任务时最多.也可以是一些服务(SOAP)的宿主,不在限制与iis,不现在限制于 ...
- Java文件操作系列[3]——使用jacob操作word文档
Java对word文档的操作需要通过第三方组件实现,例如jacob.iText.POI和java2word等.jacob组件的功能最强大,可以操作word,Excel等格式的文件.该组件调用的的是操作 ...
- Flask信号流程
首先先我们来看看Flask里面的信号是什么样的,我们可以找到一个叫signals.py的文件 这里面是所有定义了的后面请求流程中会用到的信号 二.哪些地方用到了信号 1.请求app上下文时执行的,在执 ...
- Linux远程连接及常用指令
一.远程连接 一般,服务器都是特别庞大的,会把它们用一个独立的小屋进行存放,如果有时候需要对服务器进行一些操作,离得近还好,离的远就会破费一些周折了,所以,这个时候我们就需要用到远程连接软件了.推荐使 ...
- Codeforces Round #317 (Div. 2) C Lengthening Sticks (组合,数学)
一个合法的三角形的充要条件是a<b+c,其中a为最长的一边,可以考虑找出所有不满足的情况然后用总方案减去不合法的情况. 对于一个给定的总长度tl(一定要分完,因为是枚举tl,不分配的长度已经考虑 ...
- SVN中的check out与export的区别
http://blog.csdn.net/zndxlxm/article/details/7763116 check out跟check in对应,export跟import对应. check out ...
- 通过例子理解 k8s 架构【转】
为了帮助大家更好地理解 Kubernetes 架构,我们部署一个应用来演示各个组件之间是如何协作的. 执行命令 kubectl run httpd-app --image=httpd --replic ...
- roi_pooling层
roi_pooling层先把rpn生成的roi映射到特征提取层最后一层,然后再分成7*7个bin进行池化 下面是roi_pooling层的映射到特征提取层的代码,可以看到用的是round函数,也就是说 ...
- oracle count 百万级 分页查询记要总数、总条数优化
oracle count 百万级 分页查询记录总数.总条数优化 oracle count 百万级 查询记录总数.总条数优化 最近做一个项目时,做分页时,发现分页查询速度很慢,分页我做的是两次查询,一次 ...
- iOS 面试集锦2
4.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy) ...