2525: [Poi2011]Dynamite

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 240  Solved: 120
[Submit][Status][Discuss]

Description

The Byteotian Cave is composed of  n chambers and n-1 corridors that connect them. For every pair of chambers there is unique way to move from one of them to another without leaving the cave. Dynamite charges are set up in certain chambers. A fuse is laid along every corridor. In every chamber the fuses from the adjacent corridors meet at one point, and are further connected to the dynamite charge if there is one in the chamber. It takes exactly one unit of time for the fuse between two neighbouring chambers to burn, and the dynamite charge explodes in the instant that fire reaches the chamber it is inside.
We would like to light the fuses in some m chambers (at the joints of fuses) in such a way that all the dynamite charges explode in the shortest time possible since the fuses are lit. Write a program that will determine the minimum such time possible.
 
Byteotian Cave的结构是一棵N个节点的树,其中某些点上面已经安置了炸 药,现在需要点燃M个点上的引线引爆所有的炸 药。
某个点上的引线被点燃后的1单位时间内,在树上和它相邻的点的引线会被点燃。如果一个有炸 药的点的引信被点燃,那么这个点上的炸 药会爆炸。
求引爆所有炸 药的最短时间。 输入:
第一行是两个整数N,M。(1<=m<=n<=300000)
接下来一行有N个整数Di,第I个数为1表示该点有炸 药。
接下来N-1行每行有两个数A,B,表示A和B之间有一条边。
输出:
最短时间。
样例解释: 
点燃3,5上的引线。

Input

The first line of the standard input holds two integers n and m (1<=M<=N<=300000)
, separated by a single space, that denote, respectively, the number of chambers in the cave and the number of chambers in which fire can be set to the fuses. The chambers are numbered from 1 to n . The next line contains  n integers d1,d2…dn (Di属于{0,1}, separated by single spaces. If Di=1 , then there is dynamite in the -th chamber, and if di=0 , there is none. The following n -1 lines specify the corridors of the cave. Each of them holds two integers a,b (a<=a<b<=n), separated by a single space, denoting that there is a corridor connecting the chambers a and b . Every corridor appears exactly once in the description.
You may assume that in tests worth 10% of the points it holds additionally that n<= 10, while in tests worth 40% of the points it holds that N<=1000.

Output

The first and only line of the standard output should hold a single integer, equal to the minimum time it takes from lighting the fuses to the explosion of all the charges.

Sample Input

7 2
1 0 1 1 0 1 1
1 3
2 3
3 4
4 5
5 6
5 7

Sample Output

1
  这道题还算比较水,上来以为所有点都放了炸 弹,那么果断二分答案+贪心啊。然而看到不是每个点都有炸弹后感觉这个人都不好了……
  然后果断重新想,发现二分答案还是可行的,仍然是尽可能的不到不点不行的时候点……
  然后又开始继续打码,好不容易打完了又发现自己打的还是错的,心痛……
  然而再接再厉,接着去分析。我们把所有节点分为3类。第一类,下面全是引线,没有炸弹。那么,我们可以直接忽略它。第二种,底下是炸弹,并且没有被点燃,这时,我们就要把它的子树中的离当前节点最远的状态传上来了。第三种,就是下面已经有引线被点燃,而且它有可能接着在我们规定的时间内点燃其他炸弹,与第二种相反,我们要找的是离当前节点最近的。
  在我们搜到一个点后,我们统计来自他子树的答案,如果下面都是引线,那么这个节点的状态就看他是不是炸弹了。如果他下面只有被点燃的引线,我们找到离他最近的引线转移过去,当然,如果他与引线的距离远,我们就没必要传递了。如果下面只有炸弹,我们就要看一下最远的炸弹离他是多远了。如果比当前值小,我们就直接传下去就行,否则将该点点燃,然后将状态改为点燃引线,接着传递。
  比较复杂的是下面既有被点燃的引线又有炸弹。我们需要分类讨论一下,如果引线可以点燃炸弹就把他的状态定为被点燃的引线,否则就改为炸弹,记得在这里也判断一下炸弹是否需要点燃,否则WA到死。最后判断一下根节点是什么状态,如果是炸弹我们还是要再点一个的。
 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#define N 300005
using namespace std;
int n,a[N],zz,m;
struct no
{
int to,next;
}road[N*];
void build(int x,int y)
{
zz++;
road[zz].to=y;
road[zz].next=a[x];
a[x]=zz;
}
int bom[N];
int size[N],fa[N];
void dfs1(int x)
{
size[x]=;
for(int i=a[x];i>;i=road[i].next)
{
int y=road[i].to;
if(y==fa[x])continue;
fa[y]=x;
dfs1(y);
size[x]+=size[y];
}
}
int sum,f[N],c[N];
void dfs(int x,int t)
{
if(size[x]==)
{
if(bom[x])
{
c[x]=;
f[x]=;
if(t==)
{
sum++;
f[x]=;
c[x]=;
}
}
else
{
c[x]=-;
f[x]=-;
}
return;
}
int mn=0x7fffffff,mx=-;
bool yx=;
for(int i=a[x];i>;i=road[i].next)
{
int y=road[i].to;
if(y==fa[x])continue;
dfs(y,t);
if(c[y]==-)continue;
yx=;
if(c[y]==)
{
if(f[y]+<=t) mn=min(mn,f[y]+);
} else
mx=max(mx,f[y]+);
}
if(yx)
{
c[x]=-;f[x]=-;
if(bom[x])
{
c[x]=;
f[x]=;
if(t==)
{
sum++;
c[x]=;
}
}
return;
}
if(mx==-&&mn!=0x7fffffff)
{
c[x]=;
f[x]=mn;
return;
}
if(mx==-&&mn==0x7fffffff)
{
if(bom[x])
{
c[x]=;
f[x]=;
if(t==)
{
sum++;
f[x]=;
c[x]=;
}
}
else
{
c[x]=-;
f[x]=-;
}
return;
}
if(mn==0x7fffffff)
{
if(mx>=t)
{
sum++;
f[x]=;
c[x]=;
}
else
{
c[x]=;
f[x]=mx;
}
return;
}
if(mn+mx<=t)
{
c[x]=;
f[x]=mn;
return;
}
if(mx>=t)
{
sum++;
f[x]=;
c[x]=;
}
else
{
c[x]=;
f[x]=mx;
}
}
bool check(int k)
{
memset(c,,sizeof(c));
memset(f,,sizeof(f));
sum=;
dfs(,k);
if(c[]==)sum++;
return sum<=m;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&bom[i]);
}
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
build(x,y);
build(y,x);
}
dfs1();
int li=,ri=n,mid;
while(li<=ri)
{
mid=(li+ri)>>;
if(check(mid)) ri=mid-;
else li=mid+;
}
printf("%d\n",ri+);
return ;
}

Bzoj 2525 [Poi2011]Dynamite的更多相关文章

  1. bzoj 2525 [Poi2011]Dynamite 二分+树形dp

    [Poi2011]Dynamite Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 270  Solved: 138[Submit][Status][D ...

  2. BZOJ 2525 Poi2011 Dynamite 二分答案+树形贪心

    题目大意:给定一棵树,有一些点是关键点,要求选择不超过mm个点.使得全部关键点到近期的选择的点距离最大值最小 二分答案,问题转化为: 给定一棵树,有一些点是关键点,要求选择最少的点使得每一个关键点到选 ...

  3. bzoj 2525: [Poi2011]Dynamite【二分+树上贪心】

    一眼二分.然后重点是树上贪心部分 长得像dp一样,设mn为子树内已炸点的最浅点,mx为子树内没有炸并且需要炸的最深点,然后转移直接从子树继承即可 然后是判断当前u点是否需要炸,当mx[u]+mn[u] ...

  4. 【BZOJ2525】[Poi2011]Dynamite 二分+树形DP

    [BZOJ2525][Poi2011]Dynamite Description Byteotian Cave的结构是一棵N个节点的树,其中某些点上面已经安置了炸.药,现在需要点燃M个点上的引线引爆所有 ...

  5. BZOJ 2530 Poi2011 Party 【枚举】

    BZOJ 2530 Poi2011 Party Description Byteasar intends to throw up a party. Naturally, he would like i ...

  6. [bzoj 2216] [Poi2011] Lightning Conductor

    [bzoj 2216] [Poi2011] Lightning Conductor Description 已知一个长度为n的序列a1,a2,-,an. 对于每个1<=i<=n,找到最小的 ...

  7. 【BZOJ2525】[Poi2011]Dynamite(二分,树形dp)

    [BZOJ2525][Poi2011]Dynamite Description Byteotian Cave的结构是一棵N个节点的树,其中某些点上面已经安置了炸.药,现在需要点燃M个点上的引线引爆所有 ...

  8. [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

    题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...

  9. [BZOJ 2350] [Poi2011] Party 【Special】

    题目链接: BZOJ - 2350 题目分析 因为存在一个 2/3 n 大小的团,所以不在这个团中的点最多 1/3 n 个. 牺牲一些团内的点,每次让一个团内的点与一个不在团内的点抵消删除,最多牺牲 ...

随机推荐

  1. Win8 Metro(C#)数字图像处理--2.44图像油画效果算法

    原文:Win8 Metro(C#)数字图像处理--2.44图像油画效果算法  [函数名称]   图像油画效果      OilpaintingProcess(WriteableBitmap src ...

  2. Win8Metro(C#)数字图像处理--2.22二值图像膨胀

    原文:Win8Metro(C#)数字图像处理--2.22二值图像膨胀  [函数名称] 二值图像膨胀函数DilationProcess(WriteableBitmap src) [算法说明]  膨胀 ...

  3. 加载dll、lib库(例子的代码很全)

    是关于如何加载dll或lib库的.可以看这篇bog   Qt调用dll中的功能函数点击打开链接 **************************************************** ...

  4. 零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」

    原文:零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」 本系列将教大家以实做案例认识Blend 4 的布局容器,此章介绍的是Blend 4 里的 ...

  5. Linux7下配置Nginx站点.

    今天闲来无事,把服务器重新配置了一下,作为开发者,实际上很多人都是长时间不去配置服务器的,所以曾经很多东西又忘掉了差不多. 特在此分享一下配置成功后的配置文件内容. 其实配置后的文件内容很简单,也没有 ...

  6. Creating a Linux Daemon (service) in Delphi

    With the introduction of the Linux target for Delphi, a wide range of possibilities are opened up to ...

  7. Realm_King 之 XPDL(XML Process Definition Language)

    XPDL(XML Process Definition Language)是由Workflow Management Coalition(简写为:WfMC)所提出的一个标准化规格,使用XML文件让不同 ...

  8. 第四章 自定义sol合约转化java代码,并实现调用

     鉴于笔者以前各大博客教程都有很多人提问,早期建立一个技术交流群,里面技术体系可能比较杂,想了解相关区块链开发,技术提问,请加QQ群:538327407 准备工作 1.官方参考说明文档 https:/ ...

  9. Django之F、Q查询,事务,自定义char字段

    F查询 from django.db.models import F,Q # 当查询条件来自于数据库的某个字段,这个时候就必须使用F # 查询卖出数大于库存数的商品 res = models.Prod ...

  10. 编解码器之战:AV1、HEVC、VP9和VVC

    视频Codec专家Jan Ozer在Streaming Media West上主持了一场开放论坛,邀请百余名观众参与热门Codec的各项优势与短板.本文整理了讨论的主要成果,基本代表了AV1.HEVC ...