https://www.luogu.org/problemnew/show/P2495

Dp 方程很显然

设 Dp[u] 表示——使 u 不与其子树中任意一个关键点联通的最小代价

设 w[a, b] 表示 a 与 b 之间的边的权值。

  • 若 son[i] 不是关键点,Dp[u] = Dp[u] + min{Dp[son[i]],w[u][son[i]]}
  • 若 son[i] 是关键点,Dp[u] = Dp[u] + w[u][son[i]]

但这样复杂度很显然是不对的,所以我们考虑虚树

什么,你还不会虚树?那就去跟 zzq 学吧 https://www.cnblogs.com/zzqsblog/p/5560645.html

我们发现 k 的总和与 n 同级,所以用虚树优化这个 Dp,建出虚树,在虚树上 Dp 即可

#include <bits/stdc++.h>
#define X first
#define Y second
#define mp make_pair
using namespace std; typedef long long ll;
const int N = 250000 + 5, LG2 = 18; vector < pair <int, int> > G[N], G2[N];
int pre[N][LG2 + 1], dep[N], mx[N][LG2 + 1], id[N], dfn;
int n, m, k, h[N], sta[N], len, MX;
ll f[N];
bool book[N]; void init(int u, int fa) {
pre[u][0] = fa; dep[u] = dep[fa] + 1; id[u] = ++dfn;
for(int i = 1; i <= LG2; i++) {
pre[u][i] = pre[pre[u][i - 1]][i - 1];
mx[u][i] = min(mx[u][i - 1], mx[pre[u][i - 1]][i - 1]);
}
for(vector < pair <int, int> > :: iterator it = G[u].begin(); it != G[u].end(); it++) {
int v = it -> X; if(v != fa) mx[v][0] = it -> Y, init(v, u);
}
} int LCA(int x, int y) {
MX = INT_MAX;
if(dep[x] > dep[y]) swap(x, y);
for(int i = LG2; i >= 0; i--)
if(dep[pre[y][i]] >= dep[x])
MX = min(MX, mx[y][i]), y = pre[y][i];
if(x == y) return x;
for(int i = LG2; i >= 0; i--)
if(pre[x][i] != pre[y][i]) {
MX = min(MX, min(mx[x][i], mx[y][i]));
x = pre[x][i], y = pre[y][i];
}
return pre[x][0];
} bool cmp(int x, int y) {return id[x] < id[y];} void DP(int u) {
f[u] = 0;
for(vector < pair <int, int> > :: iterator it = G2[u].begin(); it != G2[u].end(); it++) {
int v = it -> X; DP(v);
if(book[v]) f[u] += it -> Y;
else f[u] += min(f[v], (ll)it -> Y);
}
} int main() {
cin >> n;
for(int i = 1; i < n; i++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
G[a].push_back( mp(b, c) );
G[b].push_back( mp(a, c) );
}
init(1, 0); cin >> m;
while(m--) {
scanf("%d", &k);
for(int i = 1; i <= k; i++) {
scanf("%d", &h[i]);
book[h[i]] = 1;
}
sort(h + 1, h + k + 1, cmp);
sta[len = 1] = 1; G2[1].clear();
for(int i = 1; i <= k; i++) {
if(h[i] == 1) continue;
int lca = LCA(h[i], sta[len]);
if(lca != sta[len]) {
while(id[lca] < id[sta[len - 1]]) {
LCA(sta[len - 1], sta[len]);
G2[sta[len - 1]].push_back( mp(sta[len], MX) );
len--;
}
if(id[lca] > id[sta[len - 1]]) {
G2[lca].clear();
LCA(lca, sta[len]);
G2[lca].push_back( mp(sta[len], MX) );
sta[len] = lca;
} else LCA(lca, sta[len]), G2[lca].push_back( mp(sta[len], MX) ), len--;
}
G2[h[i]].clear(); sta[++len] = h[i];
}
for(int i = 1; i < len; i++) LCA(sta[i], sta[i + 1]), G2[sta[i]].push_back( mp(sta[i + 1], MX) );
DP(1); printf("%lld\n", f[1]);
for(int i = 1; i <= k; i++) book[h[i]] = 0;
}
return 0;
}

luoguP2495 [SDOI2011]消耗战的更多相关文章

  1. [luoguP2495] [SDOI2011]消耗战(DP + 虚树)

    传送门 明显虚树. 别的题解里都是这样说的. 先不考虑虚树,假设只有一组询问,该如何dp? f[u]表示把子树u中所有的有资源的节点都切掉的最优解 如果节点u需要切掉了话,$f[u]=val[u]$ ...

  2. BZOJ 2286: [Sdoi2011]消耗战

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2082  Solved: 736[Submit][Status] ...

  3. bzoj 2286: [Sdoi2011]消耗战 虚树+树dp

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...

  4. bzoj千题计划254:bzoj2286: [Sdoi2011]消耗战

    http://www.lydsy.com/JudgeOnline/problem.php?id=2286 虚树上树形DP #include<cmath> #include<cstdi ...

  5. 【LG2495】[SDOI2011]消耗战

    [LG2495][SDOI2011]消耗战 题面 洛谷 题解 参考博客 题意 给你\(n\)个点的一棵树 \(m\)个询问,每个询问给出\(k\)个点 求将这\(k\)个点与\(1\)号点断掉的最小代 ...

  6. AC日记——[SDOI2011]消耗战 洛谷 P2495

    [SDOI2011]消耗战 思路: 建虚树走树形dp: 代码: #include <bits/stdc++.h> using namespace std; #define INF 1e17 ...

  7. [BZOJ2286][SDOI2011]消耗战(虚树DP)

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4998  Solved: 1867[Submit][Statu ...

  8. BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 4261  Solved: 1552 [Submit][Sta ...

  9. 【BZOJ2286】[Sdoi2011]消耗战 虚树

    [BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...

随机推荐

  1. transfrom-runtime文档

    transfrom-runtime文档 babel只会默认对句法进行转换,而那些方法,api不会转换,要转就要使用polyfill和transform,这里介绍transform,关于polyfill ...

  2. X11 转发

    SecureCRT只支持字符界面,如果要在终端界面能弹出GUI,需要本地安装X11 server,然后服务器讲X11请求forward到本地,即可. x11 server 可以使用Xming, Xma ...

  3. 第一次调用Web service响应速度慢的解决办法

    Env: Client: WinForm(Net Framework 2.0) Server:Web Service(Net Framework 4.0) Problem: Client use pr ...

  4. linux rz -e

    linux shell rz和sz是终端下常用的文件传输命令,rz和sz通过shell被调用,其中rz用于从启用终端的系统上传文件到目标系统(终端登录的目标系统), 这里不过多介绍这些命令,只是记录一 ...

  5. linux多线程默认栈大小和最大线程数

    linux的线程栈大小可以使用ulimit -s查看,对于ubunt 2.6的内核线程栈的默认大小为8M,如下: shine@shine-bupt:~/Program/C$ ulimit -s 819 ...

  6. JDK和CGLIB生成动态代理类的区别(转)

     关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...

  7. java使用POST发送soap报文请求webservice返回500错误解析

    本文使用JAX-WS2.2编译webservice,并使用HttpUrlConnection的POST方式对wsdl发送soap报文进行请求返回数据, 对错误Server returned HTTP ...

  8. oracle一个创建用户、创建表空间、授权、建表的完整过程

    1.首先我们可以用scott用户以sysdba的身份登录oracle. conn scott/tiger as sysdba 2.然后我就可以来创建用户了. create user zzg ident ...

  9. 调用DLL的2种方式

    [调用DLL的2种方式] DLL在生成的时候会有dll.lib2个文件,另外包含相应的.h. 1.静态方式,通过lib来引用dll,以及引入.h. 2.只通过dll来使用,前提是知道内部的函数符号.

  10. FastDFS和apache/nginx整合

    因为FastDFS默认自带的http服务器性能不好, 所以一般建议用外置的apache或者nginx 来解决http下载,以应付大并发的情况 注意nginx扩展模块只支持GET和HEAD模式获取文件, ...