Atcoder ARC101 E 树dp

https://arc101.contest.atcoder.jp/tasks/arc101_c

题解是也是dp,好像是容斥做的,但是看不懂,而且也好像没讲怎么变n^2,看了写大佬的代码,自己理解了一下

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
#define X           first
#define Y           second
#define pb          push_back
#define mp          make_pair
#define SZ(X)       (X.size())
#define mst(a,b)    memset((a),(b),sizeof(a))
#define lowbit(a)   ((a)&(-a))
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
const int mod=1e9+7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn=5500;
inline int add(int x,int y){
    if((x+=y)>=mod)x-=mod;
    return x;
}
inline int mul(int x,int y){
    return (ll)x*y%mod;
}
inline int sub(int x,int y){
    if((x-=y)<0)x+=mod;
    return x;
}
int ci[maxn];
vector<int>to[maxn];
int dp[maxn][maxn];//dp[pos][i] 子树,有i个点未匹配的合法方案
                //除了根之外的子树自匹配完是不合法的,所以-dp[pos][0]表示以pos为根的子树匹配完,但pos之下子树各自之间未匹配完
int sz[maxn],uu[maxn];
void dfs(int pos,int fa){
    sz[pos]=1;
    dp[pos][1]=1;
    for(int d:to[pos])if(d!=fa){
        dfs(d,pos);
        for(int i=0;i<=sz[pos]+sz[d];++i)
            uu[i]=0;
        for(int i=0;i<=sz[pos];++i)
            for(int j=0;j<=sz[d];++j)
            uu[i+j]=add(uu[i+j],mul(dp[pos][i],dp[d][j]));
        sz[pos]+=sz[d];
        for(int i=0;i<=sz[pos];++i)
            dp[pos][i]=uu[i];
    }
    for(int i=2;i<=sz[pos];i+=2)
        dp[pos][0]=sub(dp[pos][0],mul(dp[pos][i],ci[i]));
}
int main() {
#ifdef local
    freopen("in.txt", "r", stdin);
#endif // local
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    ci[0]=1;
    for(int i=2;i<maxn;i+=2)
        ci[i]=mul(ci[i-2],i-1);
    int n;cin>>n;
    for(int i=1;i<n;++i){
        int a,b;cin>>a>>b;
        to[a].push_back(b);
        to[b].push_back(a);
    }
    dfs(1,0);
    cout<<(mod-dp[1][0]);

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/bibibi/p/9542644.html