zoukankan      html  css  js  c++  java
  • COCI2016-2017 Contest#2 F

    COCI2016-2017 Contest#2 F

    首先分析题意: 任意走都能在(k)步内结束,也就是说,一定可以在(k)步内封锁所有出路

    注意游戏停止的条件是后手不能走,因此即使在(k)步封住了出路,下一轮依然要标记一个点

    因此必须是(<k)

    设树根1的(dep=0),第(i)层表示所有(dep=i)的节点

    发现第(i)次操作,一定是从(i-1)层走到了(i)

    假设最后的封路决策在(i)层封掉了2个点,那么这个决策一定是不优的

    因为在(i)层花2的时间一定不如在(i-1)层和(i)层各花1的时间

    因此,问题可以转化为: 在(1-k)层每层选择一个点,判断是否存在一种方案使得选择完成后完全封死出路

    显然在最优情况下,选择的点之间不会有祖先关系,并且我们可以删掉所有(dep>k)的点

    因此可以写出一个(ncdot 2^k)(dp)

    由于最后要阻塞其实是阻塞所有的叶子((dep=k)的点)

    因此考虑令选择每个节点是覆盖了一段叶子,将叶子按照( ext{dfs})序从小到大依次标号,设选择(i)子树能覆盖叶子范围(L_i,R_i)

    因此按照(L_i)从小到大依次考虑每个节点,加入的转移就是

    $egin{aligned} dep_i otin S,dp_{L_i,S} ightarrow dp_{R_i+1,Scup lbrace dep_i brace }end{aligned} $

    如果用bitset实现,时间/空间复杂度均为(O(n cdot 2^{k-5}))

    如果直接(dp)显然。。。考虑缩小(k)的范围

    推论1: 当(n< frac{(k-1)cdot (k+2)}{2})时,一定有解

    考虑一个浅显的贪心: 在第(i)层用(leq i)的代价标记这层所有点

    这个方法不可用的条件就是第(i)层的点个数(>i),那么就有(nge 2+3+cdots+k=frac{(k-1)(k+2)}{2})

    可以看到此时(k)的上界已经缩小到(O(sqrt n))级别,但由于实际常数,还是太大了

    [ ]

    推论2: 当(nleq kcdot k)时,一定有解

    假设删除原树的1节点,则我们决策的对象变为一片森林

    考虑依次决策每一层,每次推进一层,都会把选择一棵树删除,并且当前森林所有顶端的节点删除

    要求(k)次决策后森林为空

    设森林第一层包含(d)个节点

    此时一定存在一个子树大小(ge frac{n}{d})

    删除这个子树后,规模变为(n-d-frac{n}{d}+1)

    我们知道(d+frac{n}{d}ge 2sqrt n)

    (n-d-frac{n}{d}+1leq n-2sqrt n+1=(sqrt n-1)^2)

    因此得证

    此时(k)的上界已经缩小到19,完全可以通过

    带入优化的复杂度为(O(ncdot 2^{15}))

    #include<bits/stdc++.h>
    
    using namespace std;
    #pragma GCC optimize(2)
    typedef long long ll;
    #define reg register
    #define pb push_back
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    int rd(){
    	int s=0;
    	while(!isdigit(IO=getchar()));
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return s;
    }
    
    const int N=410;
    
    int n,m;
    vector <int> G[N],Q[N];
    int dep[N],L[N],R[N],cnt;
    
    void pre_dfs(int u,int f) {
    	dep[u]=dep[f]+1;
    	if(dep[u]==m-1) { L[u]=cnt++,R[u]=cnt; return; }
    	L[u]=cnt;
    	for(int v:G[u]) if(v!=f) pre_dfs(v,u);
    	R[u]=cnt;
    }
    
    bitset <1<<19> dp[401],rev[20];
    int F[N]; 
    
    int main(){
    	n=rd(),m=rd();
    	if(m*m>=n) return puts("DA"),0;
    	rep(i,2,n) {
    		int u=rd(),v=rd();
    		G[u].pb(v),G[v].pb(u);
    	}
    	memset(dep,-1,sizeof dep),dep[0]=-2,pre_dfs(1,0);
    	rep(i,1,n) if(~dep[i]) Q[L[i]].pb(i);
    	dp[0][0]=1;
    	rep(i,0,m-1) rep(j,0,(1<<m)-1) if(~j&(1<<i)) rev[i][j]=1;
    	rep(i,0,cnt-1) 
    		for(int v:Q[i]) {
    			dp[R[v]]|=(dp[i]&rev[dep[v]])<<(1<<dep[v]);
    		}
    	puts(dp[cnt].count()?"DA":"NE");
    }
    
    
    
    
    
    
    
    
  • 相关阅读:
    洛谷 P3392 涂国旗
    CODEVS 1066/洛谷 P1514引水入城
    POJ 1286 Necklace of Beads(项链的珠子)
    CODEVS 1138 聪明的质监员
    洛谷 P1241 括号序列
    C++之路进阶——codevs2313(星际竞速)
    C++之路进阶——codevs2366(朋友圈)
    c++之路进阶——hdu3507(Print Article)
    C++之路进阶——codevs2404(糖果)
    C++之路进阶——codevs4655(序列终结者)
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13624017.html
Copyright © 2011-2022 走看看