zoukankan      html  css  js  c++  java
  • 「JSOI2018」潜入行动(树形dp+小优化)

    https://loj.ac/problem/2546

    直接树形dp设(f[i][j][0/1][0/1])表示(i)子树,选了(j)个,(i被覆盖了吗)(选了i吗)

    复杂度是(O(n*k^2))

    加上子树大小优化,复杂度降为(O(nk)),还有其它优化:

    考虑度数为1的点,与它唯一相邻的点必须要选。

    把必须要选的点找出来,如果(>k),则直接输出0。

    进行了这个优化后,发现要合并的(>1)的子树不超过(k)个。

    所以复杂度降为(O(nk+k^3))

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 1e9 + 7;
    
    const int N = 1e5 + 5;
    
    int n, k, x, y, r[N];
    
    vector<int> e[N];
    #define pb push_back
    #define si size()
    
    int fa[N], siz[N];
    
    int f[N][101][2][2];
    
    ll g[101][2][2];
    
    void dg(int x) {
    	siz[x] = 1;
    	f[x][0][0][0] = f[x][1][0][1] = 1;
    	ff(_y, 0, e[x].si) {
    		int y = e[x][_y]; if(y == fa[x]) continue;
    		fa[y] = x;
    		dg(y);
    		fo(i, 0, min(k, siz[x] + siz[y])) fo(j, 0, 1) fo(t, 0, 1) g[i][j][t] = 0;
    		fo(i, 0, siz[x]) fo(j, 0, 1) fo(t, 0, 1) if(f[x][i][j][t]) {
    			fo(p, 0, min(k - i, siz[y])) fo(q, !t, 1) fo(w, 0, 1) if(f[y][p][q][w]) {
    				g[i + p][j | w][t] = (g[i + p][j | w][t] + (ll) f[x][i][j][t] * f[y][p][q][w]) % mo;
    			}
    		}
    		siz[x] = min(k, siz[x] + siz[y]);
    		fo(i, 0, siz[x]) fo(j, 0, 1) fo(t, 0, 1)
    			f[x][i][j][t] = g[i][j][t] % mo;
    	}
    }
    
    int bz[N];
    
    int main() {
    	scanf("%d %d", &n, &k);
    	fo(i, 1, n - 1) {
    		scanf("%d %d", &x, &y);
    		e[x].pb(y); e[y].pb(x);
    		r[x] ++, r[y] ++;
    	}
    	int cnt = 0;
    	fo(i, 1, n) if(r[i] == 1) {
    		bz[e[i][0]] = 1;
    	}
    	fo(i, 1, n) cnt += bz[i];
    	if(cnt > k) {
    		pp("0
    ");
    		return 0;
    	}
    	dg(1);
    	ll ans = ((ll) f[1][k][1][0] + f[1][k][1][1]) % mo;
    	pp("%lld
    ", ans);
    }
    
    
  • 相关阅读:
    解决vs code just-in-time报错的方法
    c++ 右值引用
    c++11 知识点
    ip路由名词介绍&琐碎知识
    第二次结对作业
    软工程第三次作业
    第二次作业
    软件工程第一次作业
    理解Object.defineProperty()
    concat()拷贝的局限性
  • 原文地址:https://www.cnblogs.com/coldchair/p/12745744.html
Copyright © 2011-2022 走看看