[update]

好像有个东西叫笛卡尔树,好像是这样建的.....

inline void build_d() {
stk[top = ] = ;
for(int i = ; i <= n; i++) {
while(top && val[stk[top]] <= val[i]) {
ls[i] = stk[top];
top--;
}
if(ls[i]) {
fa[ls[i]] = i;
}
if(top) {
fa[i] = stk[top];
rs[stk[top]] = i;
}
stk[++top] = i;
}
RT = stk[];
return;
}

题意:给定树上k个点,求切断这些点到根路径的最小代价。∑k <= 5e5

解:虚树。

构建虚树大概是这样的:设加入点与栈顶的lca为y,比较y和栈中第二个元素的DFS序大小关系。

代码如下:

 inline bool cmp(const int &a, const int &b) {
return pos[a] < pos[b];
} inline void build_t() {
std::sort(imp + , imp + k + , cmp);
TP = top = ;
stk[++top] = imp[];
use[imp[]] = Time;
E[imp[]] = ;
for(int i = ; i <= k; i++) {
int x = imp[i], y = lca(x, stk[top]);
if(use[x] != Time) {
use[x] = Time;
E[x] = ;
}
if(use[y] != Time) {
use[y] = Time;
E[y] = ;
}
while(top > && pos[y] <= pos[stk[top - ]]) {
ADD(stk[top - ], stk[top]);
top--;
}
if(stk[top] != y) {
ADD(y, stk[top]);
stk[top] = y;
}
stk[++top] = x;
}
while(top > ) {
ADD(stk[top - ], stk[top]);
top--;
}
RT = stk[top];
return;
}

然后本题建虚树跑DP就行了。注意虚树根节点的DP初值和虚树的边权。

 #include <cstdio>
#include <algorithm> typedef long long LL;
const int N = ;
const LL INF = 1e18; struct Edge {
int nex, v;
LL len;
}edge[N << ], EDGE[N << ]; int tp, TP; int e[N], siz[N], stk[N], top, Time, n, fa[N][], k, RT, num, pos[N], pw[N], now[N], imp[N], E[N], d[N], use[N];
LL f[N], small[N][]; inline void ADD(int x, int y, LL z) {
TP++;
EDGE[TP].v = y;
EDGE[TP].len = z;
EDGE[TP].nex = E[x];
E[x] = TP;
return;
} inline void add(int x, int y, LL z) {
top++;
edge[top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top;
return;
} void DFS_1(int x, int father) { // get fa small
fa[x][] = father;
d[x] = d[father] + ;
pos[x] = ++num;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == father) {
continue;
}
small[y][] = edge[i].len;
DFS_1(y, x);
}
return;
} inline int lca(int x, int y) {
if(d[x] > d[y]) {
std::swap(x, y);
}
int t = pw[n];
while(t >= && d[x] < d[y]) {
if(d[fa[y][t]] >= d[x]) {
y = fa[y][t];
}
t--;
}
if(x == y) {
return x;
}
t = pw[n];
while(t >= && fa[x][] != fa[y][]) {
if(fa[x][t] != fa[y][t]) {
x = fa[x][t];
y = fa[y][t];
}
t--;
}
return fa[x][];
} inline bool cmp(const int &a, const int &b) {
return pos[a] < pos[b];
} inline LL getMin(int x, int y) {
LL ans = INF;
int t = pw[d[y] - d[x]];
while(t >= && y != x) {
if(d[fa[y][t]] >= d[x]) {
ans = std::min(ans, small[y][t]);
y = fa[y][t];
}
t--;
}
return ans;
} inline void build_t() {
std::sort(imp + , imp + k + , cmp);
TP = top = ;
stk[++top] = imp[];
use[imp[]] = Time;
E[imp[]] = ;
for(int i = ; i <= k; i++) {
int x = imp[i], y = lca(x, stk[top]);
if(use[x] != Time) {
use[x] = Time;
E[x] = ;
}
if(use[y] != Time) {
use[y] = Time;
E[y] = ;
}
while(top > && pos[y] <= pos[stk[top - ]]) {
ADD(stk[top - ], stk[top], getMin(stk[top - ], stk[top]));
top--;
}
if(stk[top] != y) {
ADD(y, stk[top], getMin(y, stk[top]));
stk[top] = y;
}
stk[++top] = x;
}
while(top > ) {
ADD(stk[top - ], stk[top], getMin(stk[top - ], stk[top]));
top--;
}
RT = stk[top];
return;
} void DFS(int x) {
siz[x] = (now[x] == Time);
LL temp = ;
for(int i = E[x]; i; i = EDGE[i].nex) {
int y = EDGE[i].v;
f[y] = EDGE[i].len;
DFS(y);
siz[x] += siz[y];
if(siz[y]) {
temp += f[y];
}
}
if(now[x] != Time) {
f[x] = std::min(f[x], temp);
}
return;
} void out(int x) {
return;
} int main() {
scanf("%d", &n);
/*if(n > 100) {
return -1;
}*/
int x, y; LL z;
for(int i = ; i < n; i++) {
scanf("%d%d%lld", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
// get lca min_edge
DFS_1(, );
for(int i = ; i <= n; i++) {
pw[i] = pw[i >> ] + ;
}
for(int j = ; j <= pw[n]; j++) {
for(int i = ; i <= n; i++) {
fa[i][j] = fa[fa[i][j - ]][j - ];
small[i][j] = std::min(small[i][j - ], small[fa[i][j - ]][j - ]);
}
} int m;
scanf("%d", &m);
for(Time = ; Time <= m; Time++) {
scanf("%d", &k);
//printf("\n k = %d \n", k);
for(int i = ; i <= k; i++) {
scanf("%d", &imp[i]);
now[imp[i]] = Time;
}
//printf("input over \n");
build_t();
//out(RT);
f[RT] = getMin(, RT);
DFS(RT);
printf("%lld\n", f[RT]);
} return ;
}

AC代码

[虚树模板] 洛谷P2495 消耗战的更多相关文章

  1. 【数论】卢卡斯定理模板 洛谷P3807

    [数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...

  2. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  3. 洛谷 P2495 [SDOI2011]消耗战(虚树,dp)

    题面 洛谷 题解 虚树+dp 关于虚树 了解一下 具体实现 inline void insert(int x) { if (top == 1) {s[++top] = x; return ;} int ...

  4. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  5. 洛谷P2495 [SDOI2011]消耗战(虚树)

    题面 传送门 题解 为啥一直莫名其妙\(90\)分啊--重构了一下代码才\(A\)掉-- 先考虑直接\(dp\)怎么做 树形\(dp\)的时候,记一下断开某个节点的最小值,就是从根节点到它的路径上最短 ...

  6. ●洛谷P2495 [SDOI2011]消耗战

    题链: https://www.luogu.org/problemnew/show/P2495题解: 虚树入门,树形dp 推荐博客:http://blog.csdn.net/lych_cys/arti ...

  7. 树链剖分模板(洛谷P3384)

    洛谷P3384 #include <bits/stdc++.h> #define DBG(x) cerr << #x << " = " < ...

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

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

  9. [Bzoj2286][Sdoi2011]消耗战(虚树模板题附讲解)

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

随机推荐

  1. ruby安装及升级

    在centos6.x下执行上面的"gem install redis"操作可能会报错,坑很多!默认yum安装的ruby版本是1.8.7,版本太低,需要升级到ruby2.2以上,否则 ...

  2. centos7.2部署vnc服务记录

    不做过多介绍了,下面直接记录下centos7系统下安装配置vncserver的操作记录 0)更改为启动桌面或命令行模式 获取当前系统启动模式 [root@localhost ~]# systemctl ...

  3. tomcate+keepalived配置双机热备

    环境清单: 应用1:192.168.51.101 应用2:192.168.51.75 虚拟IP:192.168.51.179 一.安装Tomcat(参照其他文档): 二.部署应用,并修改响应的端口(9 ...

  4. python-小知识点-14

    ''' python2 python3 ''' #python2 print() print 'abc' range() xrange() 生成器 raw_input() #python3 print ...

  5. cf946d 怎样逃最多的课dp

    来源:codeforces                                              D. Timetable Ivan is a student at Berland ...

  6. Glace:generator-jhipster, adding User entity enhancement management

    https://github.com/jhipster/generator-jhipster/issues/2538 jhipster,很好用的开发工具.国外知名度高,国内未普及,国外大公司在用. j ...

  7. VirtualBox 导入虚拟机时的注意事项 VDI 与VMDK

    1. 建议不要勾选  as vdi   vmdk 最好不过了.. 长个经验教训 以后尽量不勾选 vmdk 有很多工具能进行转换 vdi的 要麻烦一些.

  8. linux_软件安装

    一.在线安装(apt) APT是Advance Packaging Tool(高级包装工具)的缩写,APT可以自动下载,配置,安装二进制或者源代码格式的软件包,简化了Unix系统上管理软件的过程. 1 ...

  9. children和childNodes 的区别

    1.childNodes 属性,标准的,它返回指定元素的子元素集合,包括html节点,所有属性,文本.可以通过nodeType来判断是哪种类型的节点,只有当nodeType==时才是元素节点,是属性节 ...

  10. Log4j 日志操作包配置详解

    log4j简介 Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护 ...