[SDOI2011]消耗战
题目描述
在一场战争中,战场由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
如果是单次询问,可以$O(n)$的树dp做出来
这题询问数很多,但$k$的和不大
对于每次询问,我们建一棵“虚树”
这棵虚树只包括询问点以及相应的lca
这样在虚树上dp复杂度为$O(k)$
总复杂度为$O(\sumk)$
树dp可以这样Min[x]表示1~x路径上最小的边
f[x]表示1无法到达x子树中关键点的最小和
f[x]=min(Min[x],∑f[v])
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- typedef long long lol;
- const int N=;
- struct Node
- {
- int next,to;
- lol dis;
- }edge[N],edge2[N];
- int head[N],head2[N],num,dep[N],a[N],s[N],cnt,dfn[N];
- int fa[N][],vis[N],n,top,bin[],ed[N],M;
- lol Min[N];
- int gi()
- {
- char ch=getchar();
- int x=;
- while (ch<''||ch>'') ch=getchar();
- while (ch>=''&&ch<='')
- {
- x=x*+ch-'';
- ch=getchar();
- }
- return x;
- }
- bool cmp(int a,int b)
- {
- return dfn[a]<dfn[b];
- }
- void add(int u,int v,lol w)
- {
- num++;
- edge[num].next=head[u];
- head[u]=num;
- edge[num].to=v;
- edge[num].dis=w;
- }
- void dfs(int x,int pa)
- {int i;
- dep[x]=dep[pa]+;
- dfn[x]=++cnt;
- for (i=;bin[i]<=dep[x];i++)
- fa[x][i]=fa[fa[x][i-]][i-];
- for (i=head[x];i;i=edge[i].next)
- {
- int v=edge[i].to;
- if (v==pa) continue;
- Min[v]=min(Min[x],edge[i].dis);
- fa[v][]=x;
- dfs(v,x);
- }
- ed[x]=cnt;
- }
- int lca(int x,int y)
- {int as,i;
- if (dep[x]<dep[y]) swap(x,y);
- for (i=;i>=;i--)
- if (bin[i]<=dep[x]-dep[y])
- x=fa[x][i];
- if (x==y) return x;
- for (i=;i>=;i--)
- {
- if (fa[x][i]!=fa[y][i])
- {
- x=fa[x][i];y=fa[y][i];
- }
- }
- return fa[x][];
- }
- void add2(int u,int v)
- {
- if (u==v) return;
- num++;
- edge2[num].next=head2[u];
- head2[u]=num;
- edge2[num].to=v;
- }
- lol dp(int x)
- {int i;
- if (vis[x])
- return Min[x];
- lol tmp=;
- for (i=head2[x];i;i=edge2[i].next)
- {
- int v=edge2[i].to;
- tmp+=dp(v);
- }
- head2[x]=;
- return min(tmp,Min[x]);
- }
- int main()
- {int i,u,v,j,q,k;
- lol w;
- cin>>n;
- bin[]=;
- for (i=;i<=;i++)
- bin[i]=bin[i-]*;
- for (i=;i<=n-;i++)
- {
- scanf("%d%d%lld",&u,&v,&w);
- add(u,v,w);add(v,u,w);
- }
- Min[]=2e15;
- dfs(,);
- cin>>q;
- while (q--)
- {
- k=gi();
- M=k;
- num=;
- for (i=;i<=k;i++)
- a[i]=gi(),vis[a[i]]=;
- sort(a+,a+k+,cmp);
- for (i=;i<=k;i++)
- if (ed[a[i-]]<dfn[a[i]])
- a[++M]=lca(a[i-],a[i]);a[++M]=;
- sort(a+,a+M+,cmp);
- M=unique(a+,a+M+)-a-;
- s[++top]=a[];
- for (i=;i<=M;i++)
- {
- while (top&&ed[s[top]]<dfn[a[i]]) top--;
- add2(s[top],a[i]);
- s[++top]=a[i];
- }
- printf("%lld\n",dp());
- for (i=;i<=M;i++)
- vis[a[i]]=head2[a[i]]=;
- }
- }
[SDOI2011]消耗战的更多相关文章
- 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千题计划254:bzoj2286: [Sdoi2011]消耗战
http://www.lydsy.com/JudgeOnline/problem.php?id=2286 虚树上树形DP #include<cmath> #include<cstdi ...
- 【LG2495】[SDOI2011]消耗战
[LG2495][SDOI2011]消耗战 题面 洛谷 题解 参考博客 题意 给你\(n\)个点的一棵树 \(m\)个询问,每个询问给出\(k\)个点 求将这\(k\)个点与\(1\)号点断掉的最小代 ...
- AC日记——[SDOI2011]消耗战 洛谷 P2495
[SDOI2011]消耗战 思路: 建虚树走树形dp: 代码: #include <bits/stdc++.h> using namespace std; #define INF 1e17 ...
- [BZOJ2286][SDOI2011]消耗战(虚树DP)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4998 Solved: 1867[Submit][Statu ...
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4261 Solved: 1552 [Submit][Sta ...
- 【BZOJ2286】[Sdoi2011]消耗战 虚树
[BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...
- 2286: [Sdoi2011]消耗战
2286: [Sdoi2011]消耗战 链接 分析 虚树练习题. 构建虚树,在虚树上DP. 跟着gxb学虚-tree... 代码 #include <cstdio> #include &l ...
- BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6371 Solved: 2496[Submit][Statu ...
随机推荐
- python的PEP8 代码风格指南
PEP8 代码风格指南 这篇文章原文实际上来自于这里:https://www.python.org/dev/peps/pep-0008/ 知识点 代码排版 字符串引号 表达式和语句中的空格 注释 版本 ...
- Java 中 compareTo方法问题
compareTo方法原理:先读取出字符串的第一个“字母”进行比较,比较的方法是ascii码表的值(字符所对应的十进制值),如果前面的大那么返回1,后面的大返回-1:此位置相同,继续比较下一位,直到最 ...
- stringify 字符串转化成json方法
参照原文:http://www.cnblogs.com/damonlan/ http://www.jb51.net/article/29893.htm stringify的作用主要是序列化对象(转化为 ...
- 16-TypeScript装饰器模式
在客户端脚本中,有一个类通常有一个方法需要执行一些操作,当我们需要扩展新功能,增加一些操作代码时,通常需要修改类中方法的代码,这种方式违背了开闭的原则. 装饰器模式可以动态的给类增加一些额外的职责.基 ...
- C#中委托。
委托(delegate):是一个类型.其实winform中控件的事件也是特殊的委托类型. 如: 自定义委托:自定义委托在winform中的用法. 当要在子线程中更新UI时,必须通过委托来实现. pri ...
- Java 持久化操作之 --io流与序列化
1)File类操作文件的属性 1.File类的常用方法 1. 文件的绝对完整路径:getAbsolutePath() 文件名:getName() 文件相对路径:getPath() 文件的上一级目录:g ...
- 有货前端 Web-APM 实践
有货前端 Web-APM 实践 0 背景 有货电商技术架构上采用的是前后端分离,前端是主要以业务展示和接口聚合为主,拥有自己的 BFF (Backend For Frontend),以 nodejs ...
- Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1
摘要: Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1 安装遇到问题请文末留言. 悦动智能公众号:aibbtcom AI这个概念好像突然就 ...
- Spring Security 入门(1-2)Spring Security - 从 配置例子例子 开始我们的学习历程
1.Spring Security 的配置文件 我们需要为 Spring Security 专门建立一个 Spring 的配置文件,该文件就专门用来作为 Spring Security 的配置. &l ...
- lambda匿名函数透析
lambda匿名函数透析 目录 1 匿名函数的作用... 1 2 匿名函数的格式... 1 3 匿名函数实例代码... 3 1 匿名函数的作用 ...