洛谷P4516-JSOI潜入行动
4516-JSOI潜入行动
极其毒瘤的树dp。。
空间卡的死死的,导致LL精度问题。
思路也很难想,实现起来还有很多意想不到的坑点。。
树形dp枚举边界一旦写错复杂度会假...
另需要开一个临时数组存储当前节点根据已经遍历的子节点更新之后的dp值,DP的时候前面的状态不能保留,要开一个临时数组g更新
dp转移可以认为是用(考虑了前i个子节点的以now为根,选取j个点放置监视器+后两维状态)(也就是dp[][][now][j][0/1][0/1])的方案数*(以son为子节点,选取k个点放置监视器+后两维状态)的方案数,来更新dp[now][j+k][0/1][0/1]的值。前一个方案数可能会被覆盖更新。
没有滚动优化掉i的话大概是五维的dp,照luogu上的限制早MLE炸了...
#include <bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
#define debugg(x) cout<<#x<<'='<<x<<endl;
#define debug1(x,y,z) cout<<#x<<' '<<x<<' '<<#y<<' '<<y<<' '<<#z<<' '<<z<<endl;
#define debug cout<<endl<<"********"<<endl;
#define ll long long
#define ull unisgned long long
#define ld long double
#define itn int
#define pii pair<int,int>
#define rep(I, A, B) for (int I = (A); I <= (B); ++I)
#define dwn(I, A, B) for (int I = (A); I >= (B); --I)
#define mod (ll)(1e9+7)
#define mid ((lo+ro)>>1)
void fre(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
}
void fc(){fclose(stdin);fclose(stdout);}
const int maxn=1e5+10;
const ll inf=0x7fffffff;
int n, m;
int dp[maxn][110][2][2];
int tmp[110][2][2];
vector<int> all[maxn];
void add(int u, int v) { all[u].push_back(v); }
inline int add1(int x, ll y) {
if (y >= mod) y %= mod;
return (int)((1LL*x+y)%mod);
}
int dfs(int now,int fat){
dp[now][1][1][0]=1;dp[now][0][0][0]=1;
if (all[now].size() == 1 && all[now][0] == fat) return 1;
int sum = 1, t = 0;
for (int i = 0; i < all[now].size(); i++){
int v = all[now][i];
if (v == fat)
continue;
t = dfs(v, now);
rep(j, 0, min(sum, m)){
tmp[j][0][0] = dp[now][j][0][0];
dp[now][j][0][0] = 0;
tmp[j][1][0] = dp[now][j][1][0];
dp[now][j][1][0] = 0;
tmp[j][0][1]=dp[now][j][0][1];
dp[now][j][0][1] = 0;
tmp[j][1][1] = dp[now][j][1][1];
dp[now][j][1][1] = 0;
}
rep(j, 0, min(sum, m)){
rep(k,0,min(t,m-j)){
dp[now][j + k][0][0] = add1(dp[now][j + k][0][0],1LL * tmp[j][0][0] * dp[v][k][0][1]);
dp[now][j + k][0][1] = add1(dp[now][j + k][0][1],1LL*tmp[j][0][1] * (dp[v][k][0][1] + dp[v][k][1][1]) );
dp[now][j + k][0][1] = add1(dp[now][j + k][0][1], 1LL*tmp[j][0][0] * dp[v][k][1][1] );
dp[now][j + k][1][0] = add1(dp[now][j + k][1][0],1LL*tmp[j][1][0] * (dp[v][k][0][0] + dp[v][k][0][1]));
dp[now][j + k][1][1] = add1(dp[now][j + k][1][1],1LL*tmp[j][1][0] * (dp[v][k][1][0] + dp[v][k][1][1]));
dp[now][j + k][1][1] = add1(dp[now][j + k][1][1], 1LL*tmp[j][1][1] * (1LL*dp[v][k][1][1] + 1LL*dp[v][k][1][0] + 1LL*dp[v][k][0][0] + 1LL*dp[v][k][0][1]));
}
}
sum+=t;
}
return sum;
}
int main(){
ios;cin >> n >> m;
for (int i = 1; i < n; i++){
int a1,a2;
cin >> a1 >> a2;
add(a1, a2);
add(a2, a1);
}
dfs(1, 0);
cout << ((dp[1][m][1][1] + dp[1][m][0][1]) % mod) << endl;
return 0;
}

浙公网安备 33010602011771号