我是靠谱客的博主 俏皮烧鹅,最近开发中收集的这篇文章主要介绍【CF814E】 An unavoidable detour for home(组合数学)(DP)传送门题解:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

传送门


题解:

由题目给出的两个限制:

1.从1到所有点的最短路唯一
2.1到 i i i的距离不小于1到 i + 1 i+1 i+1的距离

我们可以很显然地发现图可以这样生成:

  1. BFS树就是最短路树,且每个点向深度浅的边的连线只有一条
  2. 同层的点的编号连续,且非树边只可能是同层的点之间的连边。

f [ i ] [ j ] f[i][j] f[i][j]表示考虑前 i i i个点的时候,最后 j j j个点和 i i i点在同一层时候的方案数。

g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k]表示这一层有 i i i个点,上一层度数为 2 2 2的点有 j j j个,度数为 3 3 3的点有 k k k个,两层之间连边加上上一层层内连边的方案数,注意这里没有考虑当前层的点之间的连边,因为在考虑下一层的时候当前层的点有可能需要向下连边。

那么很显然,根据定义,最终答案为 ∑ i = 1 n − 1 f [ n ] [ i ] ∗ g [ 0 ] [ c 0 ] [ c 1 ] sumlimits_{i=1}^{n-1}f[n][i]*g[0][c0][c1] i=1n1f[n][i]g[0][c0][c1],其中 c 0 , c 1 c0,c1 c0,c1分别表示最后 i i i个点中度数为 2 2 2 3 3 3的点的个数。

同时对于 f f f,我们通过枚举上一层有多少个点,有一个可以 O ( n 3 ) O(n^3) O(n3)求解的式子:

f [ i ] [ j ] = ∑ k = 1 i − j − 1 f [ i − j ] [ k ] ∗ g [ j ] [ c 0 ] [ c 1 ] f[i][j]=sum_{k=1}^{i-j-1}f[i-j][k]*g[j][c0][c1] f[i][j]=k=1ij1f[ij][k]g[j][c0][c1]

这里的 c 0 , c 1 c0,c1 c0,c1是从 i i i倒着数 k k k个的度数计数。

于是我们现在需要考虑的是 g g g的求解。

实际上 g g g也有一个 O ( n 3 ) O(n^3) O(n3)的求解方式。

显然 g [ 0 ] [ 0 ] [ 0 ] = 1 g[0][0][0]=1 g[0][0][0]=1

然后,考虑 g [ 0 ] [ 0 ] [ k ] g[0][0][k] g[0][0][k]怎么算。由于现在只有度数为 3 3 3的点,不需要向下连出儿子边,每个点去掉向上的父亲边之后度数为 2 2 2。所以同层连边之后剩下的是若干个环,需要考虑旋转和翻折同构,实际上就是项链数,记长度为 i i i的非同构项链总数为 a i a_i ai。但是由于不允许重边,需要去掉长度为 2 2 2的环。

枚举这个点所在的环的长度,我们有:

g [ 0 ] [ 0 ] [ k ] = ∑ l = 3 k g [ 0 ] [ 0 ] [ k − l ] ⋅ ( k − 1 l − 1 ) ⋅ a l g[0][0][k]=sum_{l=3}^{k}g[0][0][k-l]cdot{k-1choose l-1}cdot a_l g[0][0][k]=l=3kg[0][0][kl](l1k1)al

考虑算 g [ 0 ] [ j ] [ k ] g[0][j][k] g[0][j][k]。现在,由于连了父亲边了,所有度数为 2 2 2的点还有一条自由边,度数为 3 3 3的点还有两条自由边,我们可以假设最后新加入的点度数为 2 2 2(其实 3 3 3也可以,但是转移情况有三种,考虑度数为 2 2 2的话只有两种),考虑这个加入的点有一条自由边,现在强制给这条边找到另一端。

如果从度数为 2 2 2的点中选择的话方案数显然是 j − 1 j-1 j1,转化成子问题 g [ 0 ] [ j − 2 ] [ k ] g[0][j-2][k] g[0][j2][k]
如果从度数为 3 3 3的点中选择的话,这个点的自由边就只剩下一条,相当于度数为 2 2 2的点,方案数为 k k k,转化为子问题 g [ 0 ] [ j ] [ k − 1 ] g[0][j][k-1] g[0][j][k1]

所以我们得到第二个转移式:

g [ 0 ] [ j ] [ k ] = g [ 0 ] [ j − 2 ] [ k ] ⋅ ( j − 1 ) + g [ 0 ] [ j ] [ k − 1 ] ⋅ k g[0][j][k]=g[0][j-2][k]cdot(j-1)+g[0][j][k-1]cdot k g[0][j][k]=g[0][j2][k](j1)+g[0][j][k1]k

现在考虑求 g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k]。其实这里还挺简单的,我们考虑在上一层中选择一个点作为他的父亲,那么他的父亲就要少一条自由边,直接考虑一下选择度数为 2 2 2还是 3 3 3,随便做就行了,则有如下转移:

g [ i ] [ j ] [ k ] = g [ i − 1 ] [ j − 1 ] [ k ] ⋅ j + g [ i − 1 ] [ j + 1 ] [ k − 1 ] ⋅ k g[i][j][k]=g[i-1][j-1][k]cdot j+g[i-1][j+1][k-1]cdot k g[i][j][k]=g[i1][j1][k]j+g[i1][j+1][k1]k

总复杂度 O ( n 3 ) O(n^3) O(n3)所以为什么才给n=50


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline bool Inc(int &a,int b){return (a+=b)>=mod&&(a-=mod);}
inline bool Dec(int &a,int b){return (a-=b)<0&&(a+=mod);}
cs int N=55;
int n,ans;
int g[N][N][N],f[N][N],d[N];
int c[N][N],a[N];
inline void init(){
c[0][0]=1;
for(int re i=1;i<=n;++i){
c[i][0]=c[i][i]=1;
for(int re j=1;j<i;++j)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
}
a[2]=a[3]=1;
for(int re i=4;i<=n;++i)a[i]=mul(a[i-1],i-1);
g[0][0][0]=1;
for(int re k=1;k<=n;++k)
for(int re l=3;l<=k;++l)
Inc(g[0][0][k],mul(g[0][0][k-l],mul(c[k-1][l-1],a[l])));
for(int re j=1;j<=n;++j)
for(int re k=0,lk=n-j;k<=lk;++k)
(j>=2)&&Inc(g[0][j][k],mul(g[0][j-2][k],j-1)),
(k>=1)&&Inc(g[0][j][k],mul(g[0][j][k-1],k));
for(int re i=1;i<=n;++i)
for(int re j=0,lj=n-i;j<=lj;++j)
for(int re k=0,lk=lj-j;k<=lk;++k)
j&&Inc(g[i][j][k],mul(g[i-1][j-1][k],j)),
k&&Inc(g[i][j][k],mul(g[i-1][j+1][k-1],k));
}
signed main(){
scanf("%d",&n);
for(int re i=1;i<=n;++i)scanf("%d",d+i);
init();
f[d[1]+1][d[1]]=1;
for(int re i=d[1]+2;i<=n;++i)
for(int re j=1,lj=i-d[1]-1;j<=lj;++j)
for(int re k=1,lk=i-j,c0=0,c1=0;k<lk;++k){
++(d[i-j-k+1]==2?c0:c1);
Inc(f[i][j],mul(f[i-j][k],g[j][c0][c1]));
}
for(int re i=1,c0=0,c1=0;i<n;++i){
++(d[n-i+1]==2?c0:c1);
Inc(ans,mul(f[n][i],g[0][c0][c1]));
}
cout<<ans<<"n";
return 0;
}

最后

以上就是俏皮烧鹅为你收集整理的【CF814E】 An unavoidable detour for home(组合数学)(DP)传送门题解:的全部内容,希望文章能够帮你解决【CF814E】 An unavoidable detour for home(组合数学)(DP)传送门题解:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部