消耗战 bzoj 2286
消耗战
【问题描述】
在一场战争中,战场由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的更多相关文章
- BZOJ 2286: [Sdoi2011]消耗战
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2082 Solved: 736[Submit][Status] ...
- bzoj 2286: [Sdoi2011]消耗战 虚树+树dp
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 在一 ...
- bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...
- bzoj 2286(洛谷 2495) [Sdoi2011]消耗战——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2286 https://www.luogu.org/problemnew/show/P2495 ...
- bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战
放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序
https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...
- BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)
题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...
- Bzoj 2286 & Luogu P2495 消耗战(LCA+虚树+欧拉序)
题面 洛谷 Bzoj 题解 很容易想到$O(nk)$的树形$dp$吧,设$f[i]$表示处理完这$i$颗子树的最小花费,同时再设一个$mi[i]$表示$i$到根节点$1$路径上的距离最小值.于是有: ...
- BZOJ 2286 [Sdoi2011]消耗战(虚树+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题目大意] 出一棵边权树,每次给出一些关键点,求最小边割集, 使得1点与各个关 ...
随机推荐
- 2003-Can't connect to mysql server on localhost (10061)
mysql数据库出现2003-Can't connect to mysql server on localhost (10061)问题 解决办法:查看wampserver服务器是否启动,如果没有启动启 ...
- Collections
2017-01-06 22:50:43 数据结构和算法 <如何学习数据结构?>:https://www.zhihu.com/question/21318658 <How do I ...
- 拥抱.NET Core,如何开发一个跨平台类库 (1)
在此前的文章中详细介绍了使用.NET Core的基本知识,如果还没有看,可以先去了解“拥抱.NET Core,学习.NET Core的基础知识补遗”,以便接下来的阅读. 在本文将介绍如何配置类库项目支 ...
- git 行动指南
Git是一个分布式的版本管理工具. 在本地项目和服务器都会拥有版本库,本地版本库由自己控制,自由选择提交代码到服务器端 windows上也建议使用命令的方式来使用git,推荐使用客户端 :http:/ ...
- 包含LOB_Data列的表删除大量数据后表及数据库文件的收缩
最近有一张表(内含varchar(max)字段),占用空间达到240G,删除历史数据后几十万条后,空间并未得到释放. 然后用DBCC CLEANTABLE(0,tb_name,100)来释放删除记录后 ...
- 「标准」的 JS风格
首先,这份 JS风格指南已经在我司的前端团队实行半年多了: 其次,在程序员的世界里,从入行到资深都需要面对几个世界级的难题,如: 世界上最好的编辑器是什么? 是用空格还是 TAB?用空格还特么衍生出 ...
- 导入 cocoapods引入的第三方库头文件,提示找不到
解决办法: 1,Build Settings ->Header Search Paths 2, 双击 Header Search Paths 添加一个, $(PODS_ROOT), 选择项选: ...
- Atitit 图像处理类库大总结attilax qc20
Atitit 图像处理类库大总结attilax qc20 1.1. 选择与组合不同的图像处理类库1 1.2. Halcon 貌似商业工具,功能强大.1 1.3. Openvc Openvc功能也是比 ...
- iOS--高级技术
1.iOS---搜索功能 2.iOS--通讯录.蓝牙.内购.GameCenter.iCloud.Passbook等系统服务开发汇总 3.iOS-技巧性总结 4.iOS-调试技巧 5.iOS-即时通讯- ...
- css实现文本溢出显示...
在网页中显示文字内容时,经常会碰到文字内容特别长的情况,那么这个时候为了使网页看起来比较美观和简洁,会对内容进行处理.下面我们就来看一看,如何使用css来对文字溢出部分增加.... 首先来看第一种情况 ...