[update]

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

inline void build_d() {stk[top = 1] = 1;for(int i = 2; 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[1];return;
}

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

解:虚树。

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

代码如下:

 1 inline bool cmp(const int &a, const int &b) {
 2     return pos[a] < pos[b];
 3 }
 4
 5 inline void build_t() {
 6     std::sort(imp + 1, imp + k + 1, cmp);
 7     TP = top = 0;
 8     stk[++top] = imp[1];
 9     use[imp[1]] = Time;
10     E[imp[1]] = 0;
11     for(int i = 2; i <= k; i++) {
12         int x = imp[i], y = lca(x, stk[top]);
13         if(use[x] != Time) {
14             use[x] = Time;
15             E[x] = 0;
16         }
17         if(use[y] != Time) {
18             use[y] = Time;
19             E[y] = 0;
20         }
21         while(top > 1 && pos[y] <= pos[stk[top - 1]]) {
22             ADD(stk[top - 1], stk[top]);
23             top--;
24         }
25         if(stk[top] != y) {
26             ADD(y, stk[top]);
27             stk[top] = y;
28         }
29         stk[++top] = x;
30     }
31     while(top > 1) {
32         ADD(stk[top - 1], stk[top]);
33         top--;
34     }
35     RT = stk[top];
36     return;
37 }

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

  1 #include <cstdio>
  2 #include <algorithm>
  3
  4 typedef long long LL;
  5 const int N = 250010;
  6 const LL INF = 1e18;
  7
  8 struct Edge {
  9     int nex, v;
 10     LL len;
 11 }edge[N << 1], EDGE[N << 1]; int tp, TP;
 12
 13 int e[N], siz[N], stk[N], top, Time, n, fa[N][20], k, RT, num, pos[N], pw[N], now[N], imp[N], E[N], d[N], use[N];
 14 LL f[N], small[N][20];
 15
 16 inline void ADD(int x, int y, LL z) {
 17     TP++;
 18     EDGE[TP].v = y;
 19     EDGE[TP].len = z;
 20     EDGE[TP].nex = E[x];
 21     E[x] = TP;
 22     return;
 23 }
 24
 25 inline void add(int x, int y, LL z) {
 26     top++;
 27     edge[top].v = y;
 28     edge[top].len = z;
 29     edge[top].nex = e[x];
 30     e[x] = top;
 31     return;
 32 }
 33
 34 void DFS_1(int x, int father) { // get fa small
 35     fa[x][0] = father;
 36     d[x] = d[father] + 1;
 37     pos[x] = ++num;
 38     for(int i = e[x]; i; i = edge[i].nex) {
 39         int y = edge[i].v;
 40         if(y == father) {
 41             continue;
 42         }
 43         small[y][0] = edge[i].len;
 44         DFS_1(y, x);
 45     }
 46     return;
 47 }
 48
 49 inline int lca(int x, int y) {
 50     if(d[x] > d[y]) {
 51         std::swap(x, y);
 52     }
 53     int t = pw[n];
 54     while(t >= 0 && d[x] < d[y]) {
 55         if(d[fa[y][t]] >= d[x]) {
 56             y = fa[y][t];
 57         }
 58         t--;
 59     }
 60     if(x == y) {
 61         return x;
 62     }
 63     t = pw[n];
 64     while(t >= 0 && fa[x][0] != fa[y][0]) {
 65         if(fa[x][t] != fa[y][t]) {
 66             x = fa[x][t];
 67             y = fa[y][t];
 68         }
 69         t--;
 70     }
 71     return fa[x][0];
 72 }
 73
 74 inline bool cmp(const int &a, const int &b) {
 75     return pos[a] < pos[b];
 76 }
 77
 78 inline LL getMin(int x, int y) {
 79     LL ans = INF;
 80     int t = pw[d[y] - d[x]];
 81     while(t >= 0 && y != x) {
 82         if(d[fa[y][t]] >= d[x]) {
 83             ans = std::min(ans, small[y][t]);
 84             y = fa[y][t];
 85         }
 86         t--;
 87     }
 88     return ans;
 89 }
 90
 91 inline void build_t() {
 92     std::sort(imp + 1, imp + k + 1, cmp);
 93     TP = top = 0;
 94     stk[++top] = imp[1];
 95     use[imp[1]] = Time;
 96     E[imp[1]] = 0;
 97     for(int i = 2; i <= k; i++) {
 98         int x = imp[i], y = lca(x, stk[top]);
 99         if(use[x] != Time) {
100             use[x] = Time;
101             E[x] = 0;
102         }
103         if(use[y] != Time) {
104             use[y] = Time;
105             E[y] = 0;
106         }
107         while(top > 1 && pos[y] <= pos[stk[top - 1]]) {
108             ADD(stk[top - 1], stk[top], getMin(stk[top - 1], stk[top]));
109             top--;
110         }
111         if(stk[top] != y) {
112             ADD(y, stk[top], getMin(y, stk[top]));
113             stk[top] = y;
114         }
115         stk[++top] = x;
116     }
117     while(top > 1) {
118         ADD(stk[top - 1], stk[top], getMin(stk[top - 1], stk[top]));
119         top--;
120     }
121     RT = stk[top];
122     return;
123 }
124
125 void DFS(int x) {
126     siz[x] = (now[x] == Time);
127     LL temp = 0;
128     for(int i = E[x]; i; i = EDGE[i].nex) {
129         int y = EDGE[i].v;
130         f[y] = EDGE[i].len;
131         DFS(y);
132         siz[x] += siz[y];
133         if(siz[y]) {
134             temp += f[y];
135         }
136     }
137     if(now[x] != Time) {
138         f[x] = std::min(f[x], temp);
139     }
140     return;
141 }
142
143 void out(int x) {
144     return;
145 }
146
147 int main() {
148     scanf("%d", &n);
149     /*if(n > 100) {
150         return -1;
151     }*/
152     int x, y; LL z;
153     for(int i = 1; i < n; i++) {
154         scanf("%d%d%lld", &x, &y, &z);
155         add(x, y, z);
156         add(y, x, z);
157     }
158     // get lca min_edge
159     DFS_1(1, 0);
160     for(int i = 2; i <= n; i++) {
161         pw[i] = pw[i >> 1] + 1;
162     }
163     for(int j = 1; j <= pw[n]; j++) {
164         for(int i = 1; i <= n; i++) {
165             fa[i][j] = fa[fa[i][j - 1]][j - 1];
166             small[i][j] = std::min(small[i][j - 1], small[fa[i][j - 1]][j - 1]);
167         }
168     }
169
170     int m;
171     scanf("%d", &m);
172     for(Time = 1; Time <= m; Time++) {
173         scanf("%d", &k);
174         //printf("\n k = %d \n", k);
175         for(int i = 1; i <= k; i++) {
176             scanf("%d", &imp[i]);
177             now[imp[i]] = Time;
178         }
179         //printf("input over \n");
180         build_t();
181         //out(RT);
182         f[RT] = getMin(1, RT);
183         DFS(RT);
184         printf("%lld\n", f[RT]);
185     }
186
187     return 0;
188 }

AC代码

转载于:https://www.cnblogs.com/huyufeifei/p/10404454.html

[虚树模板] 洛谷P2495 消耗战相关推荐

  1. 洛谷 P2495 消耗战(虚树)

    题目链接 题意 给你个以 111 为根节点的树,树有边权 www (割断此边),多组询问每次询问给你 mmm 个点,求割断边最小花费使得 111 到这些点都不连通. 思路 询问如果组数少可以直接 O( ...

  2. 字典树模板+洛谷P2580 于是他错误的点名开始了

    题目: 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉(详情请见已结束比赛 CON ...

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

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

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

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

  5. 洛谷P2495 [SDOI2011]消耗战 | 一个典型的可以搞懂虚树的例题

    题目链接 题目大意: 给出一棵树,之后对这棵树进行q次询问,每次询问一个点集,给出使得这些点集中的点都不能直接或者间接的与1相连,需要删边的最小代价(边的代价在给树的时候给出),,点集不包含1,点集总 ...

  6. 虚树学习笔记(洛谷2495 消耗战)

    题目链接 因为辣鸡csdn,导致之前快写好的博客没了 QWQ悲伤逆流成河qwqqq 首先虚树,这个东西,我感觉是一种思想,或者是方法,而并不是一个数据结构什么的. 他主要是用来解决:给出一棵树,每次询 ...

  7. 洛谷 P2495 [SDOI2011]消耗战 题解

    题目链接 题目描述: 给你一个有边权的树,若干次询问,每次询问包含一个不含点111的kkk个点的点集,求点111与这些点都不连通的最小代价(删除一些边,代价是他们的权值和). 解题思路: 首先考虑如果 ...

  8. 洛谷 P2495 [SDOI2011]消耗战

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

  9. 【模板】线段树 2 洛谷P3373

    题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一行包含三个整数 n,m,pn,m,p,分别表示该数 ...

  10. 支配树(洛谷-P5180)

    题目描述 给定一张有向图,求从1号点出发,每个点能支配的点的个数(包括自己) 输入输出格式 输入格式: 第一行两个正整数n,mn,m,表示点数和边数 接下来mm行,每行输入两个整数u,vu,v,表示有 ...

最新文章

  1. 面试官:Java反射是什么?我回答不上来!
  2. 关于数据库插入中文乱码问题
  3. Jdk1.8新特性(二)——lambda表达式(参数列表)-{}和函数式接口@FunctionalInterface
  4. 这两天做项目出现的几个问题
  5. 清华大学-美团数字生活联合研究院成立
  6. jQuery模板和数据绑定
  7. C++编写程序:输入三角形的三边,判断三角形的类型。
  8. 关于搜索引擎原理的详细解读
  9. soapui使用教程1-基本使用和录制
  10. 如何监控Tuxedo中间件?Oralce TUXEDO监控方案
  11. 如何成为一名机器学习算法工程师?
  12. Excel ----- 身份证自动判断男女 公式
  13. DMA小区漏损治理之武林秘籍
  14. Unix/Linux存在之必然性
  15. Android Remote Service
  16. UICC 之 USIM 详解全系列——UICC基础知识介绍
  17. 办公软件excel表格_Office 办公软件教程丨Word,Excel,PPT
  18. Vue2积分商城PC端项目(六)
  19. web前端学习第一周总结
  20. Python实战案例,pywifi模块,Python暴力破译附近局域网WiFi密码

热门文章

  1. 计算机主机光驱弹不出来怎么办,光驱弹不出来怎么办,教你win10光驱弹不出来的应对办法...
  2. C++入门基础之计算使用某快递公司运输货物的运费
  3. 《Java SE编程365例》003: 我的电子书城
  4. 机器学习(聚类七)——层次聚类的优化算法
  5. 华为培养新员工的方案,值得收藏
  6. Cookie机制、属性参数
  7. 微信聊天小程序——(五、添加好友)
  8. 如何下载b站视频到本地
  9. 【前端面试之缓存】js本地缓存、浏览器缓存、服务器缓存
  10. P4568 飞行路线