潜入行动
题目大意
外星人又双叒叕要攻打地球了,外星母舰已经向地球航行!这一次,JYY
已经联系好了黄金舰队,打算联合所有 JSOIer
抵御外星人的进攻。
在黄金舰队就位之前,JYY
打算事先了解外星人的进攻计划。现在,携带了监听设备的特工已经秘密潜入了外星人的母舰,准备对外星人的通信实施监听。
外星人的母舰可以看成是一棵 个节点、 条边的无向树,树上的节点用 编号。JYY
的特工已经装备了隐形模块,可以在外星人母舰中不受限制地活动,可以神不知鬼不觉地在节点上安装监听设备。
如果在节点 上安装监听设备,则 JYY
能够监听与 直接相邻所有的节点的通信。换言之,如果在节点 安装监听设备,则对于树中每一条边 ,节点 都会被监听。特别注意放置在节点 的监听设备并不监听 本身的通信,这是 JYY
特别为了防止外星人察觉部署的战术。
JYY
的特工一共携带了 个监听设备,现在 JYY
想知道,有多少种不同的放置监听设备的方法,能够使得母舰上所有节点的通信都被监听?为了避免浪费,每个节点至多只能安装一个监听设备,且监听设备必须被用完。
解题思路
设 表示 的字数内装 个监听设备, 装了,其中 点放没放装置, 点有没有被监听到的方案数(在以 为根的子树中除 外的其它结点都被监听到了)。
咕咕咕。。。
AC CODE
#include <bits/stdc++.h>
using namespace std;
namespace fastio
{
int len = 0;
char ibuf[(1 << 20) + 1], *iS, *iT, out[(1 << 23) + 1];
int read()
{
int x = 0, t = 0;
char c = getchar();
while(c < '0' || c > '9')
{
t |= c == '-';
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return t ? -x : x;
}
char getcA()
{
char c = getchar();
while(c < 'A' || c > 'Z') c = getchar();
return c;
}
char getca()
{
char c = getchar();
while(c < 'a' || c > 'z') c = getchar();
return c;
}
void putc(char c)
{
out[len++] = c;
}
void write(int x)
{
if(x < 0) putc('-'), x = -x;
if(x > 9) write(x / 10);
putc(x % 10 + 48);
}
struct af
{
~af()
{
fwrite(out, 1, len, stdout);
len = 0;
}
} Af;
}
using namespace fastio;
#define _ 100005
const long long mod = 1e9 + 7;
int n, k;
int siz[_];
int dp[_][105][2][2], tmp[105][2][2];
int tot, head[_], to[_ << 1], nxt[_ << 1];
void add(int u, int v)
{
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
void dfs(int u, int fa)
{
siz[u] = dp[u][0][0][0] = dp[u][1][1][0] = 1;
for(int e = head[u]; e; e = nxt[e])
{
int v = to[e];
if(v == fa) continue;
dfs(v, u);
memcpy(tmp, dp[u], sizeof tmp);
memset(dp[u], 0, sizeof dp[u]);
for(int i = 0; i <= min(siz[u], k); ++i)
{
for(int j = 0; i + j <= k && j <= min(siz[v], k - i); ++j)
{
dp[u][i + j][0][0] = (dp[u][i + j][0][0] + (long long)1ll * tmp[i][0][0] * dp[v][j][0][1]) % mod;
dp[u][i + j][0][1] = (dp[u][i + j][0][1] + (long long)1ll * tmp[i][0][1] * (dp[v][j][0][1] + dp[v][j][1][1])) % mod;
dp[u][i + j][0][1] = (dp[u][i + j][0][1] + (long long)1ll * tmp[i][0][0] * dp[v][j][1][1]) % mod;
dp[u][i + j][1][0] = (dp[u][i + j][1][0] + (long long)1ll * tmp[i][1][0] * (dp[v][j][0][0] + dp[v][j][0][1])) % mod;
dp[u][i + j][1][1] = (dp[u][i + j][1][1] + (long long)1ll * tmp[i][1][0] * (dp[v][j][1][0] + dp[v][j][1][1])) % mod;
dp[u][i + j][1][1] = (dp[u][i + j][1][1] + (long long)1ll * tmp[i][1][1] * (1ll * dp[v][j][0][0] + dp[v][j][0][1] + 1ll * dp[v][j][1][0] + dp[v][j][1][1])) % mod;
}
}
siz[u] += siz[v];
}
}
signed main()
{
n = read(), k = read();
for(int i = 1; i < n; ++i)
{
int u = read(), v = read();
add(u, v);
add(v, u);
}
dfs(1, -1);
cout << (dp[1][k][0][1] + dp[1][k][1][1]) % mod << endl;
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122113