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


    【BZOJ2525】[Poi2011]Dynamite

    Description

    Byteotian Cave的结构是一棵N个节点的树,其中某些点上面已经安置了炸.药,现在需要点燃M个点上的引线引爆所有的炸.药。
    某个点上的引线被点燃后的1单位时间内,在树上和它相邻的点的引线会被点燃。如果一个有炸.药的点的引信被点燃,那么这个点上的炸.药会爆炸。
    求引爆所有炸.药的最短时间。
    输入:
    第一行是两个整数N,M。(1<=m<=n<=300000)
    接下来一行有N个整数Di,第I个数为1表示该点有炸.药。
    接下来N-1行每行有两个数A,B,表示A和B之间有一条边。
    输出:
    最短时间。
    样例解释: 
    点燃3,5上的引线。

    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

    题解:一眼想到二分+贪心,但是细节还是极其多的~

    首先二分时间limit,然后用f[i]表示i子树中,最少要点燃多少引线。但是i子树中的部分炸.药可能由i子树外的点引燃,所以设g[i]表示在f[i]最小的前提下,最少有多少层还没有被点燃;i子树中的引线也可能引燃子树外的炸.药,所以h[i]表示在f[i]最小的前提下,最多还能点燃子树外的多少层炸.药。显然g[x]和h[x]同时只能存在一个。

    转移时细节挺多的,见代码吧~

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=300010;
    int n,m,cnt,mid;
    int to[maxn<<1],next[maxn<<1],head[maxn],d[maxn],f[maxn],g[maxn],h[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    inline void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void dfs(int x,int fa)
    {
    	int i,y;
    	if(d[x])	g[x]=0,h[x]=-1<<20;
    	else	g[x]=h[x]=-1<<20;
    	f[x]=0;
    	for(i=head[x];i!=-1;i=next[i])	if(to[i]!=fa)
    	{
    		y=to[i],dfs(y,x),f[x]+=f[y],g[x]=max(g[x],g[y]+1),h[x]=max(h[x],h[y]-1);
    	}
    	if(h[x]>=g[x])	g[x]=-1<<20;
    	else	if(g[x]<mid)	h[x]=-1<<20;
    	else	f[x]++,g[x]=-1<<20,h[x]=mid;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,a,b,l=0,r=n;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	d[i]=rd();
    	for(i=1;i<n;i++)	a=rd(),b=rd(),add(a,b),add(b,a);
    	while(l<r)
    	{
    		mid=(l+r)>>1,dfs(1,0);
    		if(g[1]>=0)	f[1]++;
    		if(f[1]<=m)	r=mid;
    		else	l=mid+1;
    	}
    	printf("%d",r);
    	return 0;
    }//5 0 0 0 0 0 0 1 2 2 3 3 4 4 5

     

  • 相关阅读:
    数据库创建索引的缺点,和什么时候不该创建索引
    创建数据库,表,索引,删除索引,查看表中的索引和如何使用表中的索引
    java容器中 哪些是线程安全的
    java中集合类详解
    高并发 问题怎么解决
    数据库20个问题(关于事务、存储引擎、索引、悲观锁乐观锁)
    数据库事务(什么是事务)
    Application对象详解
    get和post 两种基本请求方式的区别
    BZOJ1003物流運輸 DP + SPFA
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7859067.html
Copyright © 2020-2023  润新知