消耗战

【问题描述】

在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。

侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

【输入格式】

第一行一个整数n,代表岛屿数量。

接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。

第n+1行,一个整数m,代表敌方机器能使用的次数。

接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。

【输出格式】

输出有m行,分别代表每次任务的最小代价。

【样例输入】

10

1 5 13

1 9 6

2 1 19

2 4 8

2 3 91

5 6 8

7 5 4

7 8 31

10 7 9

3

2 10 6

4 5 7 8 3

3 9 4 6

【样例输出】

12

32

22

【数据规模和约定】

对于10%的数据,2<=n<=10,1<=m<=5,1<=ki<=n-1

对于20%的数据,2<=n<=100,1<=m<=100,1<=ki<=min(10,n-1)

对于40%的数据,2<=n<=1000,m>=1,sigma(ki)<=500000,1<=ki<=min(15,n-1)

对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1


题解:

题目就是给定一棵树,询问删去一些边使输入关键节点与根节点1不连通的最小费用

虚树就是保留只所有关键节点和它们的公共祖先的连边所构建出的树,每次询问O(mlog2m)

我们记val[i]为使根节点与i不连通的最小花费

ti[i]表示i的Dfs序

对于每次询问

将所有关键节点按ti排序(根节点自然也算关键节点)

将相邻关键节点的最近公共祖先加入数组,这样就可以将所有关键节点的公共祖先

小小证明一下能够找出所有公共祖先:

  我们假定按Dfs序排好的三个点A,B,C

  如果其中两个或三个在同一个子树中,那么显然能够找出所有公共祖先

  如果都不在同一棵子树上,那么设A与B的公共祖先为D,B与C的公共祖先为E

  接下来A到根节点的链简称A链,其它同理

  因为它们按Dfs序处理过,公共祖先必定在根节点分别与两点组成的链上

  由此可知D和E都在B链上

  假设D在E的上方,那么D就是A与C的最近公共祖先

  证明:

    由于D在A链上,E在C链上

    那么D链是A链与C链的共同部分

    所以A和C的公共祖先在D链上

    由于D链在B链上

    所以在D链上离A最近的点是A与B的公共祖先即D

    则D为A、C的公共祖先

    

    E在D的上方同理

  多个点同理

  一小部分的证明自己脑补啦~~~也可以去看虚树讲义

草率地证明完毕

证明有毒但是代码巨短

再次排序,去重

接下来用单调栈连接所有关键节点之间的边

大概讲一下单调栈:

  我们已经将点按Dfs序排序过了

  所以那么我们就可以直接判断栈顶元素与当前元素的关系,即当前元素是否在栈顶元素的子树中,同时满足能顺序访问每个点的子树

  如果在子树中,那么连边,权值为当前节点的val

  如果不在,那么说明当前元素在栈顶元素子树的外边,退栈,继续判断两者关系

这样就够出了一个虚树

接下来再来一个简单的树形Dp就好了

~\(≧▽≦)/~啦啦啦

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
inline int Get()
{
int x = ;
char c = getchar();
while('' > c || c > '') c = getchar();
while('' <= c && c <= '')
{
x = (x << ) + (x << ) + c - '';
c = getchar();
}
return x;
}
const int me = ;
struct shape
{
int lca, mi;
};
int n;
int m;
int k;
int ns, s[me];
int tot, to[me], nex[me], fir[me];
long long va[me];
inline void Ins(int x, int y, int z)
{
nex[++tot] = fir[x];
fir[x] = tot;
to[tot] = y;
va[tot] = z;
}
int de[me];
int si[me];
int fa[me][];
int nt, ti[me];
long long val[me];
bool mark[me];
void Dfs(int u, int fat)
{
si[u] = ;
de[u] = de[fat] + ;
ti[u] = ++nt;
for(int i = fir[u]; i; i = nex[i])
{
int v = to[i];
if(v == fat) continue;
fa[v][] = u;
val[v] = min(val[u], va[i]);
Dfs(v, u);
si[u] += si[v];
}
}
inline bool rt(int x, int y)
{
return ti[x] < ti[y];
}
inline int Lca(int x, int y)
{
if(de[x] < de[y]) swap(x, y);
for(int i = k; de[x] != de[y], i >= ; --i)
if(de[fa[x][i]] >= de[y])
x = fa[x][i];
for(int i = k; i >= ; --i)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
if(x != y) return fa[x][];
return x;
}
long long Dp(int u, int fat)
{
if(mark[u] || !fir[u]) return val[u];
long long sum = ;
for(int i = fir[u]; i; i = nex[i])
{
int v = to[i];
if(v == fat) continue;
sum += min(Dp(v, u), val[v]);
}
return sum;
}
void Clear(int u, int fat)
{
for(int i = fir[u]; i; i = nex[i])
{
int v = to[i];
if(v == fat) continue;
Clear(v, u);
}
fir[u] = ;
}
int top, st[me];
int main()
{
n = Get();
k = log(n) + ;
for(int i = ; i < n; ++i)
{
int u = Get();
int v = Get();
int z = Get();
Ins(u, v, z);
Ins(v, u, z);
}
for(int i = ; i <= n; ++i) val[i] = 214748364721474836LL;
Dfs(, );
for(int j = ; j <= k; ++j)
for(int i = ; i <= n; ++i)
fa[i][j] = fa[fa[i][j - ]][j - ];
for(int i = ; i <= n; ++i) fir[i] = ;
tot = ;
m = Get();
for(int i = ; i <= m; ++i)
{
int p = Get();
for(int i = ; i <= p; ++i)
{
s[i] = Get();
mark[s[i]] = true;
}
sort(s + , s + + p, rt);
ns = p;
s[++ns] = ;
for(int i = ; i < p; ++i)
s[++ns] = Lca(s[i], s[i + ]);
sort(s + , s + + ns, rt);
int lens = ;
for(int i = ; i <= ns; ++i)
if(s[i] != s[i - ])
s[++lens] = s[i];
top = ;
for(int i = ; i <= lens; ++i)
{
while(top > && ti[s[i]] >= ti[st[top]] + si[st[top]]) --top;
if(top > ) Ins(st[top], s[i], val[s[i]]);
st[++top] = s[i];
}
printf("%lld\n", Dp(, ));
for(int i = ; i <= lens; ++i) mark[s[i]] = false;
tot = ;
Clear(, );
}
}

消耗战 bzoj 2286的更多相关文章

  1. BZOJ 2286: [Sdoi2011]消耗战

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

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

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

  3. bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...

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

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

  5. bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战

    放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...

  6. BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序

    https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...

  7. BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)

    题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...

  8. Bzoj 2286 & Luogu P2495 消耗战(LCA+虚树+欧拉序)

    题面 洛谷 Bzoj 题解 很容易想到$O(nk)$的树形$dp$吧,设$f[i]$表示处理完这$i$颗子树的最小花费,同时再设一个$mi[i]$表示$i$到根节点$1$路径上的距离最小值.于是有: ...

  9. BZOJ 2286 [Sdoi2011]消耗战(虚树+树形DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题目大意] 出一棵边权树,每次给出一些关键点,求最小边割集, 使得1点与各个关 ...

随机推荐

  1. Git小技巧 - 指令别名及使用Beyond Compare作为差异比较工具

    前言 本文主要写给使用命令行来操作Git的用户,用于提高Git使用的效率.至于使用命令还是GUI(Tortoise Git或VS的Git插件)就不在此讨论了,大家根据自己的的喜好选择就好.我个人是比较 ...

  2. 通过AngularJS实现前端与后台的数据对接(一)——预备工作篇

    最近,笔者在做一个项目:使用AngularJS,从而实现前端与后台的数据对接.笔者这是第一次做前端与后台的数据对接的工作,因此遇到了许多问题.笔者在这些问题中,总结了一些如何实现前端与后台的数据对接的 ...

  3. C#语法糖大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  4. mac下生成ssh keys 并上传github仓储

    使用github仓储需要本机生成一个公钥key 添加到自己的git账户SSH keys中   mac 生成方法:   1. 打开终端 输入   ssh-keygen 然后系统提示输入文件保存位置等信息 ...

  5. JS案例之2——cycle元素轮播

    元素轮播效果是页面中经常会使用的一种效果.这个例子实现了通过元素的隐藏和显示来表现轮播效果.效果比较简单. 效果图如下: 源代码如下: <!DOCTYPE html> <html&g ...

  6. RavenDB官网文档翻译系列第一

    本系列文章主要翻译自RavenDB官方文档,有些地方做了删减,有些内容整合在一起.欢迎有需要的朋友阅读.毕竟还是中文读起来更亲切吗.下面进入正题. 起航 获取RavenDB RavenDB可以通过Nu ...

  7. .NET基础拾遗(2)面向对象的实现和异常的处理基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  8. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  9. Spring学习记录(十三)---基于xml文件配置AOP

    上一篇讲了用注解配置AOP,现在讲用xml怎么配置AOP 其实逻辑是一样的,只是用xml的方法,要把这种逻辑写出来,告诉spring框架去执行. 例子:这里的例子和上一篇的例子一样.换成xml方式 / ...

  10. 【Win 10应用开发】延迟加载图片的另一种方法

    上一篇文章中老周给大伙介绍了x:Phase和x:Bind的用法,并演示了一个延迟加载的示例.不过,那个例子会遗留一个问题,就是UI线程被阻塞,所以启动应用较慢. 如果希望图片可以延迟加载,或许我们可以 ...