• 【LOJ】#2546. 「JSOI2018」潜入行动


    题解

    dp[i][j][0/1][0/1]表示以(i)为根的子树,用了(j)个,i点选了或者没选,i点被覆盖或没被覆盖

    转移比较显然,但是复杂度感觉不太对?

    其实转移到100个的时候就使第二维满了,之后每多两个点一定会多一个守卫,这个时候会使第二维某些位置开始空了,最后转移其实只有后几维有效

    具体优化的方法就是我枚举每个儿子的j的时候,只有j所在的位置有值我们才枚举父亲背包大小来更新

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 100005
    #define eps 1e-8
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int N,K;
    
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE,siz[MAXN];
    int dp[MAXN][105][2][2],g[2][4][105];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    void dfs(int u,int fa) {
        siz[u] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	}
        }
        memset(g,0,sizeof(g));
        int cur = 0;
        for(int i = 0 ; i <= 3 ; ++i) g[cur][i][0] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    int t = min(K,siz[v]),h = min(K,siz[u] + siz[v]);
    	    memset(g[cur ^ 1],0,sizeof(g[cur ^ 1]));
    	    for(int j = 0 ; j <= t ; ++j) {
    		if(!dp[v][j][0][0] && !dp[v][j][0][1] && !dp[v][j][1][0] && !dp[v][j][1][1]) continue;
    		int a[4];
    		a[0] = dp[v][j][0][1];
    		a[1] = inc(dp[v][j][0][1],dp[v][j][1][1]);
    		a[2] = inc(dp[v][j][0][1],dp[v][j][0][0]);
    		a[3] = inc(inc(dp[v][j][0][0],dp[v][j][0][1]),inc(dp[v][j][1][0],dp[v][j][1][1]));
    		for(int k = h ; k >= j ; --k) {
    		    update(g[cur ^ 1][0][k],mul(g[cur][0][k - j],a[0]));
    		    update(g[cur ^ 1][1][k],mul(g[cur][1][k - j],a[1]));
    		    update(g[cur ^ 1][2][k],mul(g[cur][2][k - j],a[2]));
    		    update(g[cur ^ 1][3][k],mul(g[cur][3][k - j],a[3]));
    		}
    		
    	    }
    	    siz[u] += siz[v];
    	    cur ^= 1;
    	}
        }
        int t = min(K,siz[u]);
        for(int i = 0 ; i <= t ; ++i) {
    	update(g[cur][1][i],MOD - g[cur][0][i]);
    	update(g[cur][3][i],MOD - g[cur][2][i]);
    	update(dp[u][i][0][0],g[cur][0][i]);
    	update(dp[u][i][0][1],g[cur][1][i]);
    	update(dp[u][i + 1][1][0],g[cur][2][i]);
    	update(dp[u][i + 1][1][1],g[cur][3][i]);
        }
    }
    void Solve() {
        read(N);read(K);
        int u,v;
        for(int i = 1 ; i < N ; ++i) {
    	read(u);read(v);
    	add(u,v);add(v,u);
        }
        dfs(1,0);
        out(inc(dp[1][K][1][1],dp[1][K][0][1]));enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    CSS---伪类
    CSS---选择器
    CSS---如何引用样式表
    HTML-- 表单
    HTML-- 文本标签
    HTML--连接、锚点
    HTML--表格
    递归算法
    PHPCMS V9 友情链接的调用
    thinkcmf跳转用户登录和个人中心页面时出现Call to undefined function sp_sql_posts()错误
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10004513.html
Copyright © 2020-2023  润新知