int val=min(min(dp[v][0],dp[v][1]),dp[v][2]); dp[u][0]+=val;
统计方案数也非常简单,只要等于最小值,都可以加入最佳方案
1 2 3 4 5
ll temp=0; for (registerint i=0;i<=2;++i){ if (dp[v][i]==val) Add(temp,cnt[v][i]);//加入方案 } Mul(cnt[u][0],temp);
2.u由孩子节点支配:
这种情况是最复杂的:
1 2 3 4 5 6 7 8
val=min(dp[u][1]+min(dp[v][0],dp[v][1]),dp[u][2]+dp[v][0]); temp=0; for (registerint i=0;i<=1;++i) { if (dp[u][1]+dp[v][i]==val) Add(temp,cnt[v][i]); } Mul(cnt[u][1],temp); if (dp[u][2]+dp[v][0]==val) Add(cnt[u][1],cnt[u][2]*cnt[v][0]%MOD); dp[u][1]=val;//要最后更新
/* 定义: dp[i][0]: 点i属于支配集,并且以点i为根的子树都被覆盖了的情况下支配集中包含的最少点数 也就是i支配自己 dp[i][1]: 点i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于1个子节点覆盖的情况下支配集包含的最少点数 也就是i的孩子支配i dp[i][2]: 点i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集包含的最少点数 也就是i由父亲支配 */ #include<bits/stdc++.h> #define INF 0x3f3f3f3f #define memmax(a) memset(a,0x3f,sizeof(a)) #define MAXN 500005 #define MOD 1032992941 #define ll long long #define int long long usingnamespace std; inlineintread(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+(ch-'0'); ch=getchar(); } return x*f; } vector<int>G[MAXN]; voidAddEdge(int u,int v){ G[u].push_back(v); G[v].push_back(u); } int dp[MAXN][3]; ll cnt[MAXN][3]; voidAdd(ll &A,ll B){ A=(A+B)%MOD; } voidMul(ll &A,ll B){ A=(A*B)%MOD; } voiddfs(int u,int father){ dp[u][0]=1;dp[u][1]=INF;dp[u][2]=0;//INF不能太大 cnt[u][0]=cnt[u][1]=cnt[u][2]=1;//因为方案是乘起来的 for (registerint i=0;i<G[u].size();++i){ int v=G[u][i]; if (v!=father){ dfs(v,u); //---------------------------------------------------------- //只要u支配了自己,剩下怎样都可以 int val=min(min(dp[v][0],dp[v][1]),dp[v][2]); dp[u][0]+=val;
ll temp=0; for (registerint i=0;i<=2;++i){ if (dp[v][i]==val) Add(temp,cnt[v][i]); } Mul(cnt[u][0],temp);
//---------------------------------------------------------- //1.u由其中一个子节点支配,子节点由自己或是孩子支配,而不由u支配 //2.u由父亲支配,子节点支配自己 val=min(dp[u][1]+min(dp[v][0],dp[v][1]),dp[u][2]+dp[v][0]); temp=0; for (registerint i=0;i<=1;++i) { if (dp[u][1]+dp[v][i]==val) Add(temp,cnt[v][i]); } Mul(cnt[u][1],temp); if (dp[u][2]+dp[v][0]==val) Add(cnt[u][1],cnt[u][2]*cnt[v][0]%MOD);
dp[u][1]=val;//要最后更新
//---------------------------------------------------------- //u由父亲支配,子节点只能支配自己 //(子节点不能由父亲支配,因为u没有;也不能由自己支配,因为u仅仅由父亲支配) dp[u][2]+=dp[v][1]; Mul(cnt[u][2],cnt[v][1]); } } } #undef int intmain(){ #define int long long int n=read(); for (registerint i=1;i<n;++i){ AddEdge(read(),read()); } dfs(1,0); int val=min(dp[1][0],dp[1][1]);//1没有父亲 ll ans=0; for (registerint i=0;i<=1;++i) { if (dp[1][i]==val) Add(ans,cnt[1][i]); } printf("%d\n%lld\n",val,ans); }