zoukankan      html  css  js  c++  java
  • [JSOI2018]潜入行动

    [JSOI2018]潜入行动

    题目大意:

    一棵(n(nle10^5))个结点的树,在一些点上安装(k(klemin(n,100)))个装置。每个装置可以控制所有与安装位置相邻的结点(不包括本身)。每个点可以安装至多一个装置。问有多少种方案恰好用完(k)个装置,使得所有的结点都被控制。

    思路:

    树形DP。(f[i][j][0/1][0/1])表示以(i)为根的子树内安装了(j)个装置,(i)本身是否安装,(i)是否被控制。手动讨论转移:

    f[x][j+k][0][0]+=f[y][k][0][1]*g[j][0][0]
    f[x][j+k][0][1]+=f[y][k][0][1]*g[j][0][1]
    f[x][j+k][0][1]+=f[y][k][1][1]*g[j][0][1]
    f[x][j+k][0][1]+=f[y][k][1][1]*g[j][0][0]
    f[x][j+k][1][0]+=f[y][k][0][0]*g[j][1][0]
    f[x][j+k][1][0]+=f[y][k][0][1]*g[j][1][0]
    f[x][j+k][1][1]+=f[y][k][1][0]*g[j][1][0]
    f[x][j+k][1][1]+=f[y][k][1][1]*g[j][1][0]
    f[x][j+k][1][1]+=f[y][k][0][0]*g[j][1][1]
    f[x][j+k][1][1]+=f[y][k][0][1]*g[j][1][1]
    f[x][j+k][1][1]+=f[y][k][1][0]*g[j][1][1]
    f[x][j+k][1][1]+=f[y][k][1][1]*g[j][1][1]
    

    需要卡常数和内存。

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    typedef long long int64;
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=1e5+1,M=101,mod=1e9+7;
    int m,size[N],f[N][M][2][2],g[M][2][2],h[N];
    struct Edge {
    	int to,next;
    };
    Edge e[N<<1];
    inline void add_edge(const int &u,const int &v) {
    	e[++h[0]]=(Edge){v,h[u]};h[u]=h[0];
    	e[++h[0]]=(Edge){u,h[v]};h[v]=h[0];
    }
    void dfs(const int &x,const int &par) {
    	f[x][0][0][0]=f[x][1][1][0]=size[x]=1;
    	for(unsigned i=h[x];i;i=e[i].next) {
    		const int &y=e[i].to;
    		if(y==par) continue;
    		dfs(y,x);
    		for(register int j=std::min(size[x],m);~j;j--) {
    			g[j][0][0]=f[x][j][0][0];
    			g[j][0][1]=f[x][j][0][1];
    			g[j][1][0]=f[x][j][1][0];
    			g[j][1][1]=f[x][j][1][1];
    			f[x][j][0][0]=f[x][j][0][1]=f[x][j][1][0]=f[x][j][1][1]=0;
    		}
    		for(register int j=std::min(size[x],m);~j;j--) {
    			for(register int k=std::min(size[y],m-j);~k;k--) {
    				(f[x][j+k][0][0]+=(int64)f[y][k][0][1]*g[j][0][0]%mod)%=mod;
    				(f[x][j+k][0][1]+=((int64)f[y][k][1][1]*(g[j][0][1]+g[j][0][0])+(int64)f[y][k][0][1]*g[j][0][1])%mod)%=mod;
    				(f[x][j+k][1][0]+=(int64)(f[y][k][0][0]+f[y][k][0][1])*g[j][1][0]%mod)%=mod;
    				(f[x][j+k][1][1]+=((int64)(f[y][k][1][0]+f[y][k][1][1])*g[j][1][0]+((int64)f[y][k][0][0]+f[y][k][0][1]+f[y][k][1][0]+f[y][k][1][1])%mod*g[j][1][1])%mod)%=mod;
    			}
    		}
    		size[x]+=size[y];
    	}
    }
    int main() {
    	const int n=getint();m=getint();
    	for(register int i=1;i<n;i++) {
    		add_edge(getint(),getint());
    	}
    	dfs(1,0);
    	printf("%d
    ",(f[1][m][0][1]+f[1][m][1][1])%mod);
    	return 0;
    }
    
  • 相关阅读:
    kali linux之wireshark/tcpdump
    kali linux之netcat
    kali 插耳机没声音
    php代码审计10审计会话认证漏洞
    php代码审计9审计反序列化漏洞
    php代码审计8审计文件上传漏洞
    Python opencv 形态学
    图像与轮廓检测-轮廓检测
    Python操作Excel,openpyxl模块,画折线图
    Pthon强制删除非空文件夹
  • 原文地址:https://www.cnblogs.com/skylee03/p/9169146.html
Copyright © 2011-2022 走看看