The 15th Chinese Northeast Collegiate Programming Contest
正文
题目描述
给出一棵树,每次可以删去任意点,要求删完后不能有孤立的点,求方案数。
题目思路及代码
大概很容易看出来是个树形dp,状态不太好想。 d p [ u ] [ 0 ] 表示删去这个点 d p [ u ] [ 1 ]表示不删这个点,而且删去所有子节点 d p [ u ] [ 2 ] 表示不删这个点,而且至少留一个子节点 对于第一种情况,此时的u一定满足条件; 对于第二种情况,要求u的父亲节点也不被删去才可以满足条件; 对于第三种情况,此时的u已经满足条件了。
dp[x][0]=(dp[v][0]+dp[v][2])%mod*dp[x][0]%mod;
dp[x][1]=dp[v][0]*dp[x][1]%mod;
如果删去u的话,那么想让子节点v满足条件,可以删除v,也可以不删v并且至少保留v的一个子节点; 如果不删u并且删去所有子节点的话,说明节点v是被删除的状态。 对于dp[u][2]可以用所有合法的方案数减去不合法的方案数。 最后答案就是dp[1][0]+dp[1][2]
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll maxn=2e5+10;
const ll mod=998244353;
vector<ll> g[maxn];
ll n,t;
ll dp[maxn][10];
void dfs(ll x,ll u){
dp[x][0]=dp[x][1]=dp[x][2]=1;
for(int i=0;i<g[x].size();i++){
ll v=g[x][i];
if(v==u)continue;
dfs(v,x);
dp[x][0]=(dp[v][0]+dp[v][2])%mod*dp[x][0]%mod;
dp[x][1]=dp[v][0]*dp[x][1]%mod;
dp[x][2]=(dp[v][0]+dp[v][1]+dp[v][2])%mod*dp[x][2]%mod;
}
dp[x][2]=(dp[x][2]-dp[x][1]+mod)%mod;
return ;
}
int main()
{
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
for(int i=1;i<n;i++){
ll x,y;
scanf("%lld%lld",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,-1);
ll ans=0;
ans=(ans+dp[1][0]+dp[1][2])%mod;
printf("%lld\n",ans);
for(int i=1;i<=n;i++){
g[i].clear();
dp[i][0]=dp[i][1]=dp[i][2]=0;
}
}
return 0;
}
结语
“遇事不决,可问春风。春风不语,即随本心。”的意思是:对一件事犹豫不决,就问春风该如何做,春风给不出答案,就凭自己本心做出决断。“遇事不决可问春风,春风不语即随本心”一句出自网络作家“烽火戏诸侯”的《剑来》,其原文是:“遇事不决,可问春风。春风不语,遵循己心”。
|