[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. Flutter - TabBar导航栏切换后,状态丢失

    上一篇讲到了 Flutter - BottomNavigationBar底部导航栏切换后,状态丢失 里面提到了TabBar,这儿专门再写一下吧,具体怎么操作,来不让TabBar的状态丢失.毕竟大家99 ...

  2. cordova打包webapp

    cordova打包webapp 在项目开发中,需要将h5页面打包成app,这个时候我们可以使用cordova来打包.在官方文档中,我们可以了解到创建一个app十分简单,你的电脑上有nodejs就行,我 ...

  3. C. Party Lemonade

    链接 [http://codeforces.com/group/1EzrFFyOc0/contest/913/problem/C] 分析 看代码,巧妙的贪心 代码 #include<bits/s ...

  4. spring boot之mybatis配置

    配置在application.yml文件中 mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Map ...

  5. 个人阅读作业2:结合《No Silver Bullet》谈谈我在软件开发过程的遇到的困难与体会

    英文捉急,只能挑一段看得比较懂的,而且正好和我们现在编程任务联系比较紧密的内容来谈一谈体会. 在<No Silver Bullet>中,作者描述了造成软件本质性困难(essence)的四个 ...

  6. 个人博客作业Week7(阅读文章,心得体会)

    Alpha阶段结束了,内心可以说是五味杂陈.不是说我们的产品拿不上台面那般差劲,复杂的心绪主要来源于和别的队的比较,别的队才刚刚发布没多久访问量和注册量就破百了,并且还发起了找bug送红包的活动.可能 ...

  7. Linux内核及分析 第六周 分析Linux内核创建一个新进程的过程

    实验过程 1.github上克隆相应的mengning/menu.git 2.测试menuOS,测试fork直接执行结果 3.配置调试系统,进入gdb调试,利用file linux-3.18.6/vm ...

  8. C++拷贝控制

    一.拷贝控制操作 ​ 当定义一个类时,显示或隐式地指定了此类型的对象在拷贝.赋值和销毁时所执行的操作,通过三个特殊的成员函数来控制这些操作,分别是拷贝构造函数,赋值运算符和析构函数.拷贝构造函数定义了 ...

  9. [转帖] linux下面 vim 数字键无法插入的解决办法

    感谢原作者: https://blog.csdn.net/guoyuqi0554/article/details/11477597 这个问题困扰自己好久了.. 刚才解决了 rlwrap的问题 这会儿 ...

  10. dotnet core 安装

    sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c 'echo -e "[packa ...