题意:
n
n
n 个点构成若干条链,每个点有一个权值且可以选任意次,父节点的选择次数必须严格大于子结点,求最后权值总和为
T
T
T 的方案数
题解:
由于是严格大于,所以对于一条链,从叶子节点往上,先依次选择 0 , 1 , 2 , 3... 0,1,2,3... 0,1,2,3... 次,然后把子结点的权值变成本身加父节点权值之和,这样选择子结点就相当于子结点和父节点一起选,保证父节点选择次数一直大于子结点
void problem_solver() {
int n,m,T; cin>>n>>m>>T;
vector<int>a(n+1),son(n+1),head(n+1,1),dep(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
vector b=a;
for(int i=0;i<m;i++){
int u,v; cin>>u>>v;
son[u]=v,head[v]=0;
}
function<void(int)>dfs=[&](int u){
if(son[u]){
a[son[u]]+=a[u];
dfs(son[u]);
dep[u]=dep[son[u]]+1;
}
};
for(int i=1;i<=n;i++) if(head[i]) dfs(i);
for(int i=1;i<=n;i++) T-=dep[i]*b[i];
if(T<0){
cout<<0<<'\n';
return;
}
vector<int>dp(T+1);
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=a[i];j<=T;j++)
dp[j]=(dp[j-a[i]]+dp[j])%mod;
cout<<dp[T]<<'\n';
}