题目大意:有一棵$n(n\leqslant2.5\times10^5)$个节点的带边权的树,$m$个询问,每次询问给出$k(\sum\limits_{i=1}^mk_i\leqslant5\times10^5)$个点,要求用最小的代价砍断一些边,使得$1$号点与这$k$个点都不连通,输出最小代价

题解:先考虑一个一次$O(n)$的$DP$,可以把所有子树内没有特殊点的点先删去,令$f(i)$表示把他于他子树内所有的特殊点割断所需要的代价,即为$\sum\limits_{v\in son_u}\min\{w,f_v\}$($w$为这条边边权,若$v$为关键点,$f_v=\inf$)。这样的复杂度是$O(n^2)$的,不可以通过。

可以建虚树,一般建一棵虚树的复杂度是$O(k\log_2n)$的,它可以使得建出来的树中只包含最多$2k$个节点。于是就可以通过本题

卡点:最多$2k$个点,$k\leqslant n$,没有开两倍的空间

C++ Code:

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
namespace std {
struct istream {
#define M (1 << 25 | 3)
char buf[M], *ch = buf - 1;
inline istream() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
fread(buf, 1, M, stdin);
}
inline istream& operator >> (int &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
#undef M
} cin;
struct ostream {
#define M (1 << 25 | 3)
char buf[M], *ch = buf - 1;
inline ostream& operator << (int x) {
if (!x) {*++ch = '0'; return *this;}
static int S[11], *top; top = S;
while (x) {*++top = x % 10 ^ 48; x /= 10;}
for (; top != S; --top) *++ch = *top;
return *this;
}
inline ostream& operator << (long long x) {
if (!x) {*++ch = '0'; return *this;}
static int S[20], *top; top = S;
while (x) {*++top = x % 10 ^ 48; x /= 10;}
for (; top != S; --top) *++ch = *top;
return *this;
}
inline ostream& operator << (const char x) {*++ch = x; return *this;}
inline ~ostream() {
#ifndef ONLINE_JUDGE
freopen("output.txt", "w", stdout);
#endif
fwrite(buf, 1, ch - buf + 1, stdout);
}
#undef M
} cout;
} #define maxn 250010 int head[maxn], cnt;
struct Edge {
int to, nxt, w;
} e[maxn << 1];
inline void addedge(int a, int b, int c) {
e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
} int in[maxn], out[maxn], idx, dep[maxn];
namespace Tree {
#define M 17
int fa[maxn][M + 1], Min[maxn][M + 1];
void dfs(int u) {
in[u] = ++idx;
for (int i = 1; i <= M; i++) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
Min[u][i] = std::min(Min[u][i - 1], Min[fa[u][i - 1]][i - 1]);
}
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != *fa[u]) {
*fa[v] = u;
*Min[v] = e[i].w;
dep[v] = dep[u] + 1;
dfs(v);
}
}
out[u] = idx;
}
inline int LCA(int x, int y) {
if (dep[x] < dep[y]) std::swap(x, y);
for (int i = dep[x] - dep[y]; i; i &= i - 1) x = fa[x][__builtin_ctz(i)];
if (x == y) return x;
for (int i = M; ~i; i--) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return *fa[x];
}
const int inf = 0x3f3f3f3f;
inline int query(int x, int k) {
int res = inf;
for (int i = k; i; i &= i - 1) {
res = std::min(res, Min[x][__builtin_ctz(i)]);
x = fa[x][__builtin_ctz(i)];
}
return res;
}
#undef M
} int n, m;
namespace Work {
const long long inf = 0x3f3f3f3f3f3f3f3f;
inline bool cmp(int a, int b) {return in[a] < in[b];} int k;
int list[maxn << 1], S[maxn], top;
long long f[maxn];
bool imp[maxn]; void dfs(int u) {
f[u] = 0;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs(v);
f[u] += std::min(f[v], static_cast<long long> (e[i].w));
}
if (imp[u]) f[u] = inf, imp[u] = false;
head[u] = 0;
} void solve() {
cnt = 0;
std::cin >> k;
for (int i = 0; i < k; i++) {
std::cin >> list[i];
imp[list[i]] = true;
} std::sort(list, list + k, cmp);
int tot = k;
for (int i = 0; i < k - 1; i++) list[tot++] = Tree::LCA(list[i], list[i + 1]);
list[tot++] = 1;
tot = (std::sort(list, list + tot, cmp), std::unique(list, list + tot) - list);
top = 0;
for (int I = 0, i = *list; I < tot; I++, i = list[I]) {
while (top && out[S[top]] < in[i]) top--;
if (top) addedge(S[top], i, Tree::query(i, dep[i] - dep[S[top]]));
S[++top] = i;
} dfs(1);
std::cout << f[1] << '\n';
}
} int main() {
std::cin >> n;
for (int i = 1, u, v, w; i < n; i++) {
std::cin >> u >> v >> w;
addedge(u, v, w);
addedge(v, u, w);
}
Tree::dfs(1);
std::cin >> m;
memset(head, 0, sizeof head);
while (m --> 0) Work::solve();
return 0;
}

  

[洛谷P2495][SDOI2011]消耗战的更多相关文章

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

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

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

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

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

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

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

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

  5. bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...

  6. [洛谷P2459] SDOI2011 消耗战

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

  7. [bzoj2286] [洛谷P2495] [sdoi2015] 消耗战

    Description 在一场战争中,战场由 \(n\) 个岛屿和 \(n-1\) 个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足 ...

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

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

  9. [洛谷P2491] [SDOI2011]消防

    洛谷题目链接:[SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超 ...

随机推荐

  1. P1803 凌乱的yyy

    P1803 凌乱的yyy 题目背景 快noip了,yyy很紧张! 题目描述 现在各大oj上有n个比赛,每个比赛的开始.结束的时间点是知道的. yyy认为,参加越多的比赛,noip就能考的越好(假的) ...

  2. 分析Android :java.lang.UnsatisfiedLinkError: dlopen failed * is 32-bit instead of 64-bit

    Crash 日志: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.ireader.plug.sdk/iread ...

  3. NSNull Crash处理 (NullSafe 的原理)

    问题场景 后端返回的数据中总会出现一些NSNull类型,当我们一处理程序就会崩溃,因此想到把返回的数据中的NSNull类型全部转换成@""空字符串 (1)原始的json串:后端返回 ...

  4. Windows运行机理——窗口句柄和消息

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 现在我们将消息与句柄联系起来.假如有一个窗口,且拥有该窗口的一个句柄( ...

  5. ReadyAPI创建功能测试的方法

    声明:如果你想转载,请标明本篇博客的链接,请多多尊重原创,谢谢! 本篇使用的 ReadyAPI版本是2.5.0 在ReadyAPI中有多种方法可以创建功能测试,本篇将分步操作创建功能测试. 1.从So ...

  6. Java开发工程师(Web方向) - 02.Servlet技术 - 第4章.JSP

    第4章--JSP JSP JSP(Java Server Pages) - 中文名:Java服务器页面 动态网页技术标准 JSP = Html + Java + JSP tags 在服务器端执行,返回 ...

  7. Java 集合学习--HashMap

    一.HashMap 定义 HashMap 是一个基于散列表(哈希表)实现的键值对集合,每个元素都是key-value对,jdk1.8后,底层数据结构涉及到了数组.链表以及红黑树.目的进一步的优化Has ...

  8. 227. Mock Hanoi Tower by Stacks【LintCode java】

    Description In the classic problem of Towers of Hanoi, you have 3 towers and N disks of different si ...

  9. 一种跨平台的C++遍历目录的方法

    参考了网络上各路大神的实现方法.主要使用了io.h库 #include <iostream> #include <cstring> #include <io.h> ...

  10. 【机器学习】线性回归python实现

    线性回归原理介绍 线性回归python实现 线性回归sklearn实现 这里使用python实现线性回归,没有使用sklearn等机器学习框架,目的是帮助理解算法的原理. 写了三个例子,分别是单变量的 ...