1 条题解

  • 0
    @ 2026-4-29 9:55:49

    注意到每个结点由唯一的水豚管理一定是不劣的,一只水豚管理超过 22 个结点一定可以构造吃不到橙子的情况。

    于是问题转化成:将该树划分成若干个大小不超过 22 的连通块,每个连通块染黑一个点,求染色的方案数。

    考虑到 N6000N\le 6000,不妨设 fu,s,0/1/2f_{u,s,0/1/2} 表示:uu 的子树中,染了 ss 个点,点 uu 和父亲一个联通块且 uu 不染色的方案数 / 点 uu 与儿子一个连通块的方案数 / 点 uu 是黑点且不与儿子在一个连通块的方案数。

    然后就变成树形背包了,复杂度 O(N2)\mathcal O(N^2)

    AC 代码(#define int 要记得 undef)。

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define mid ((l+r)>>1)
    #define bmid ((l+r+1)>>1)
    #define pb push_back
    #define eb emplace_back
    using namespace std;
    using ll= long long;
    #ifndef ONLINE_JUDGE
    template <typename tp>
    void _debug(const tp& t) {cerr<<t<<'\n';}
    template <typename tp,typename... args>
    void _debug(const tp& t, const args&... rest) {cerr<<t<<' ';_debug(rest...);}
    #define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)
    #else
    #define debug(...) 0
    #endif
    #define int ll
    const int N=6005,H=N<<2,inf=1000000000,mod=998244353;
    inline void add(int& x,ll y) {
    	x=(x+y)%mod;
    }
    vector<int> gr[N];
    int siz[N],f[N][N][3],g[N][3];
    void cut(int i) {
    	for(int j=0;j<N;j++)
    		for(int k=0;k<3;k++) {
    			g[j][k]=f[i][j][k];
    			f[i][j][k]=0;
    		}
    }
    void dfs(int u,int fa) {
    	siz[u]=1,f[u][0][0]=f[u][1][2]=1;
    	for(int& v: gr[u]) if(v!=fa) {
    		dfs(v,u);
    		cut(u);
    		for(int i=0;i<=siz[u];i++) {
    			for(int j=0;j<=siz[v];j++) {
    				add(f[u][i+j][0],g[i][0]*f[v][j][1]);
    				add(f[u][i+j][1],g[i][0]*f[v][j][2]);
    				add(f[u][i+j][1],g[i][1]*(f[v][j][1]+f[v][j][2]));
    				add(f[u][i+j][1],g[i][2]*f[v][j][0]);
    				add(f[u][i+j][2],g[i][2]*(f[v][j][1]+f[v][j][2]));
    			}
    		}
    		siz[u]+=siz[v];
    	}
    }
    #undef int
    std::vector<int> solve(int N,std::vector<int> U,std::vector<int> V) {
    	for(int i=0;i+1<N;i++) {
    		U[i]++,V[i]++;
    		gr[U[i]].pb(V[i]),gr[V[i]].pb(U[i]);
    	}
    	dfs(1,0);
    	std::vector<int> ret(N+1);
    	for(int i=0;i<=N;i++)
    		ret[i]=(f[1][i][1]+f[1][i][2])%mod;
    	return ret;
    }
    //signed main() {
    //	cin.tie(nullptr)->sync_with_stdio(false);
    //	int nn;
    //	vector<int> u,v;
    //	cin>>nn;
    //	for(int x,y,i=1;i<nn;i++) {
    //		cin>>x>>y;
    //		u.pb(x),v.pb(y);
    //	}
    //	for(int i: solve(nn,u,v)) cout<<i<<' ';
    //	return 0;
    //}
    
    • 1

    信息

    ID
    9618
    时间
    750ms
    内存
    1512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者