"JSOI2018" se cuela en la acción (dp en forma de árbol + pequeña optimización)

https://loj.ac/problem/2546

Árbol directo dp set \ (f [i] [j] [0/1] [0/1] \) para representar \ (i \) subárbol, \ (j \) seleccionado, \ (se sobrescribe \\ , \ (elegí i \)

La complejidad es \ (O (n * k ^ 2) \) .

Además de la optimización del tamaño del subárbol, la complejidad se reduce a \ (O (nk) \) , y hay otras optimizaciones:

Considerando el punto con grado 1, se debe seleccionar el único punto adyacente a él.

Averigüe los puntos que deben seleccionarse, si \ (> k \) , luego genera directamente 0.

Después de esta optimización, se descubrió que no había más de \ ( > 1 \) subárboles para fusionar .

Entonces la complejidad se reduce a \ (O (nk + k ^ 3) \)

Código:

#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("\n")
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\n");
		return 0;
	}
	dg(1);
	ll ans = ((ll) f[1][k][1][0] + f[1][k][1][1]) % mo;
	pp("%lld\n", ans);
}

Supongo que te gusta

Origin www.cnblogs.com/coldchair/p/12745744.html
Recomendado
Clasificación