2286: [Sdoi2011]消耗战

Time Limit: 20 Sec  Memory Limit: 512 MB
[Submit][Status][Discuss]

Description

在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

Input

第一行一个整数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,表示资源丰富岛屿的编号。

Output

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

Sample Input

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

Sample Output

12
32
22

HINT

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

Source

思路:虚树建树+树形dp;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<bitset>
#include<time.h>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define eps 1e-8
#define bug(x) cout<<"bug"<<x<<endl;
const int N=3e5+,M=1e6+,inf=1e9+,MOD=1e9+;
const LL INF=1e18+,mod=1e9+; struct edge
{
int v,w,next;
}edge[N<<];
int head[N],fa[N][],edg,deep[N];
int in[N],out[N],tot,mi[N][];
void init()
{
memset(head,-,sizeof(head));
edg=;tot=;
}
void add(int u,int v,int w)
{
edg++;
edge[edg].v=v;
edge[edg].w=w;
edge[edg].next=head[u];
head[u]=edg;
}
void dfs(int u,int fat)
{
tot++;
in[u]=tot;
for (int i=; i<= ;i++)
{
fa[u][i] = fa[fa[u][i-]][i-];
mi[u][i] = min(mi[u][i-],mi[fa[u][i-]][i-]);
}
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
int w=edge[i].w;
if(v==fat) continue;
deep[v]=deep[u]+;
fa[v][]=u;
mi[v][]=w;
dfs(v,u);
}
out[u]=tot;
}
int RMQ_LCA(int x,int y) {
if(deep[x]<deep[y]) swap(x,y);
int d=deep[x]-deep[y];
for (int i=; i<= ;i++)
if((<<i)&d) x=fa[x][i];
for (int i=; i>= ;i--) {
if(fa[x][i]!=fa[y][i]) {
x=fa[x][i];y=fa[y][i];
}
}
if(x==y) return x;
else return fa[x][];
}
int getmi(int x,int y)//虚树保证在一条链上
{
int z=deep[y]-deep[x];
int ans=inf;
for(int i=;i<=;i++)
if(z&(<<i))ans=min(ans,mi[y][i]),y=fa[y][i];
return ans;
} int h[M];
struct f
{
int v,w,nex;
}edge2[N<<];
int head2[N],edg2;
void add2(int u,int v,int w)
{
edge2[++edg2]=(f){v,w,head2[u]};
head2[u]=edg2;
}
bool cmp(int u, int v) {
return in[u] < in[v];
}
bool check(int u, int v) {
return in[u] <= in[v] && in[v] <= out[u];
}
int build(int A[], int tot)
{
std::sort(A + , A + + tot, cmp);
for(int i = , old_tot = tot; i <= old_tot; i++)
A[++tot] = RMQ_LCA(A[i - ], A[i]);
std::sort(A + , A + + tot, cmp);
tot = std::unique(A + , A + + tot) - A - ;
std::stack<int> S; S.push(A[]);
for(int i = ; i <= tot; i++) {
while(!S.empty() && !check(S.top(), A[i])) S.pop();
int u = S.top(), v = A[i]; // u是v的祖先
int w=getmi(u,v);
add2(u,v,w);
add2(v,u,w);//u, v, deep[v] - deep[u]);
S.push(v);
}
return tot;
}
LL dp[N];
int cnt[N];
void dfs2(int u,int fa,LL pre)
{
LL si=;
for(int i=head2[u];i!=-;i=edge2[i].nex)
{
int v=edge2[i].v;
int w=edge2[i].w;
if(v==fa)continue;
dfs2(v,u,w);
si+=dp[v];
}
if(cnt[u])dp[u]=pre;
else dp[u]=min(pre,si);
}
int main()
{
init();
memset(head2,-,sizeof(head2));
int n;
scanf("%d",&n);
for(int i=;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
dfs(,);
int q;
scanf("%d",&q);
while(q--)
{
edg2=;
int t;
scanf("%d",&t);
for(int i=;i<=t;i++)
scanf("%d",&h[i]),cnt[h[i]]=;
h[++t]=;
t = build(h, t);
dfs2(,,INF);
printf("%lld\n",dp[]);
for(int i=;i<=t;i++)
head2[h[i]]=-,cnt[h[i]]=;
}
return ;
}

2286: [Sdoi2011]消耗战

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 4080  Solved: 1476
[Submit][Status][Discuss]

Description

在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

Input

第一行一个整数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,表示资源丰富岛屿的编号。

Output

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

Sample Input

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

Sample Output

12
32
22

HINT

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

Source

bzoj 2286: [Sdoi2011]消耗战 虚树+树dp的更多相关文章

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

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

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

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

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

    题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...

  4. BZOJ 2286 [Sdoi2011]消耗战 ——虚树

    虚树第一题. 大概就是建一颗只与询问有关的更小的新树,然后在虚树上DP #include <map> #include <ctime> #include <cmath&g ...

  5. BZOJ 2286: [Sdoi2011]消耗战 虚树

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

  6. BZOJ 2286: [Sdoi2011]消耗战

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

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

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

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

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

  9. BZOJ 2286: [Sdoi2011消耗战 [DP 虚树]

    传送门 题意: 删除价值和最小的边使得$1$号点与$k$个关键点不连通 一个树形DP...但是询问多次,保证总的关键点数为$O(n)$ 先说一下这个$DP$ $f[i]$表示子树$i$中的关键点与$1 ...

随机推荐

  1. urlib库的使用

    urlib库实际上不是很常用,因为其api调用复杂,已被requests模块取代. 1.request发送请求 from urllib import request #默认指定的是get请求 #url ...

  2. 接口测试工具-tamper data

    1.火狐浏览器插件 安装:1)打开火狐浏览器-alt键-附加组件-搜索tamper data-安装-重启火狐浏览器-在工具下打开tamper data 使用:start tamper 示例:http: ...

  3. python迭代-如何实现反向迭代

    如何实现反向迭代 问题举例 实现一个连续浮点数发生器FloatRange,根据给定范围(start, end)和步进值(step) 产生一系列连续的浮点数,如FloatRange(3.0, 4.0, ...

  4. 谷歌将一些弱小的库从安卓代码移除Google Removes Vulnerable Library from Android

    Google this week released the November 2018 set of security patches for its Android platform, which ...

  5. 分享一段js,判断是否是在iPhone中的Safari浏览器打开的页面

    头部引用jquery包 将下面的一段js写在</body>的前面 <script type="text/javascript"> var ua = navi ...

  6. vue进阶--外卖商家页

    一.准备工作 1.vue特性:轻量级.简洁.高效.组件化.数据驱动 2.技术分析:使用vue- resource与后端交互(ajax通信,ie9+)  使用vue-router作为前端路由   bet ...

  7. ld命令

    ld 用于把目标代码文件连接为可执行文件或者库文件 参数 -b: 指定目标代码输入文件的格式 -Bstatic: 只使用静态库 -Bdynamic: 只使用动态库 -Bsymbolic: 把引用捆绑到 ...

  8. java中String字符串的==解析

    今天不知道怎么看了下string的==的问题,本身我觉得我这个水平去判断几个字符串相等还能出问题?呵呵,真的出了大问题,根本原因在于对java字节码的不了解. 首先,==运算符比较的是两个变量所指向的 ...

  9. Angular4 管道

  10. 2018-2019-2 《网络对抗技术》 Exp1 PC平台逆向破解 20165215

    2018-2019-2 <网络对抗技术> Exp1 PC平台逆向破解 20165215 目录 知识点描述 实验步骤 (一)直接修改程序机器指令,改变程序执行流程 (二)通过构造输入参数,造 ...