2286: [Sdoi2011]消耗战

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 4998  Solved: 1867
[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

[Submit][Status][Discuss]

首先如果一个关键点是另一个点的子孙,则这个点显然不用考虑。

剩下的就是DP,注意到状态只会在各个关键点的LCA处考虑,于是虚树DP即可。

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
const ll inf=1e15;
ll pre[N];
int n,m,k,u,v,w,tim,top,a[N],d[N],fa[N][],dfn[N],stk[N]; bool cmp(int a,int b){ return dfn[a]<dfn[b]; } struct E{
int cnt,h[N],to[N<<],nxt[N<<],val[N<<];
void add(int u,int v,int w=){ to[++cnt]=v; val[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt; }
}G1,G2; void dfs(int x){
d[x]=d[fa[x][]]+; dfn[x]=++tim;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
for (int i=G1.h[x],k; i; i=G1.nxt[i])
if ((k=G1.to[i])!=fa[x][])
fa[k][]=x,pre[k]=min((ll)G1.val[i],pre[x]),dfs(k);
} int lca(int x,int y){
if (d[x]<d[y]) swap(x,y);
int t=d[x]-d[y];
for (int i=; ~i; i--) if ((t>>i)&) x=fa[x][i];
if (x==y) return x;
for (int i=; ~i; i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
} ll dp(int x){
if (!G2.h[x]) return pre[x];
ll res=;
for (int i=G2.h[x]; i; i=G2.nxt[i]) res+=dp(G2.to[i]);
G2.h[x]=; return min(res,pre[x]);
} void build(){
stk[top=]=; int p=;
rep(i,,k) if (lca(a[i],a[p])!=a[p]) a[++p]=a[i];
rep(i,+(a[]==),p){
int x=lca(a[i],stk[top]);
while (top> && dfn[stk[top-]]>=dfn[x])
G2.add(stk[top-],stk[top]),top--;
if (x!=stk[top]) G2.add(x,stk[top]),stk[top]=x;
stk[++top]=a[i];
}
while (top>) G2.add(stk[top-],stk[top]),top--;
} int main(){
freopen("bzoj2286.in","r",stdin);
freopen("bzoj2286.out","w",stdout);
scanf("%d",&n);
rep(i,,n) scanf("%d%d%d",&u,&v,&w),G1.add(u,v,w),G1.add(v,u,w);
pre[]=inf; dfs(); scanf("%d",&m);
rep(i,,m){
scanf("%d",&k); G2.cnt=;
rep(j,,k) scanf("%d",&a[j]);
sort(a+,a+k+,cmp); build(); printf("%lld\n",dp());
}
return ;
}

[BZOJ2286][SDOI2011]消耗战(虚树DP)的更多相关文章

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

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

  2. 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP

    [题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...

  3. BZOJ2286: [Sdoi2011]消耗战(虚树/树形DP)

    Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5246  Solved: 1978[Submit][Status][Discuss] Descript ...

  4. bzoj2286: [Sdoi2011]消耗战 虚树

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

  5. [SDOI2011]消耗战(虚树+树形动规)

    虚树dp 虚树的主要思想: 不遍历没用的的节点以及没用的子树,从而使复杂度降低到\(\sum\limits k\)(k为询问的节点的总数). 所以怎么办: 只把询问节点和其LCA放入询问的数组中. 1 ...

  6. [SDOI2011][bzoj2286] 消耗战 [虚树+dp]

    题面: 传送门 思路: 看到所有询问中的点数总和是十万级别的,就想到用虚树~\(≧▽≦)/~啦 首先,树形dp应该是很明显可以看出来的: 设dp[u]表示以u为根的子树(不包括u)中的宝藏岛全部切断的 ...

  7. 【BZOJ2286】[Sdoi2011]消耗战 虚树

    [BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...

  8. 【BZOJ-2286】消耗战 虚树 + 树形DP

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

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

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

随机推荐

  1. NSObject class和NSObject protocol的关系(抽象基类与协议)

    [转载请注明出处] 1.接口的实现 对于接口这一概念的支持,不同语言的实现形式不同.Java中,由于不支持多重继承,因此提供了一个Interface关键词.而在C++中,通常是通过定义抽象基类的方式来 ...

  2. 通用套接字选项和TCP套接字选项

    1. 套接字选项函数原型: #include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void ...

  3. java多线程以及Android多线程

    Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果. 进程:在操作系统来说,一个运行的程序或者 ...

  4. SSD算法及Caffe代码详解(最详细版本)

    SSD(single shot multibox detector)算法及Caffe代码详解 https://blog.csdn.net/u014380165/article/details/7282 ...

  5. 【LabVIEW技巧】LabVIEW OOP怎么学

    前言 有很多人对LabVIEW OOP存在比较极端的看法,大致分为两类: 1. 绝对否定派认为LabVIEW OOP只不过是LabVIEW为了追求时髦,在面向过程的基础上用簇做了一些特性,实际上完全不 ...

  6. [总结]可重用cell的定义方式

    1.简介 为了提高tableview中cell的加载速度通常可以使用cell重用的方式来实现,即我们向上拖动cell的时候,上部份消失的cell可以重复的被下部分出现的cell重用. 2.说明 一般c ...

  7. 《Java编程思想》阅读笔记一

    Java编程思想 这是一个通过对<Java编程思想>(Think in java)第四版进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会 ...

  8. linux命令(3):rpm命令

    查询当前环境是否已安装软件包,如下命令: [root@cloud ~]# rpm -qa | grep httpd httpd-2.4.6-31.el7.centos.1.x86_64 httpd-t ...

  9. C语言 反序打印字符串中的单词

    int main() { char *str = "see you later"; int r = strlen(str); char * p = str; ; while(*st ...

  10. poj 2104(线段树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 45653   Accepted: 15177 Ca ...