• LOJ6094 归乡迷途


    归乡迷途

    有一张 (n) 个节点组成的无向图,点从 (1)(n) 编号,图中没有重边和自环。我们不知道它的确切形态,但是它满足以下条件:

    • 由任一节点至节点 (1) 的最短路径(经过边数最少的路径)存在且唯一;

    • (ell_i) 表示由节点 (i) 至节点 (1) 的最短路径上边的数目,那么对于所有 (2 leq i leq n),有 (ell_i geq ell_{i-1}) 成立;

    • 节点 (i) 的度数给定,为 (d_i),并且所有 (d_i) 均等于 (2)(3)

    请计算满足条件的不同的图的数目,输出其除以 (10^9 + 7) 的余数。两张无向图不同当且仅当存在点对 ((u, v) (1 leq u < v leq n)) 使得其中一张图中 ((u, v)) 间有边而另一张图中没有。

    (3 leq n leq 300,2 leq d_i leq 3)

    题解

    https://jklover.hs-blog.cf/2020/07/18/Loj-6094-归乡迷途/#more

    bfs 树 + dp 计数问题.

    限制可以简单归纳为,图的 bfs 树中,每个点的父亲编号小于自己,且非树边只在同一深度的点间出现.

    对 bfs 树进行 dp, 每一层加入的数都一定是编号连续的一段,并且只需要记录上一层的信息就可以转移.

    (f(i,j)) 表示考虑了前 (i) 个点,最深的一层有 (j) 个点,前 (i-j) 个点度数已经满足限制,最后 (j) 个点只考虑向父亲连边.

    (g(i,j,k)) 表示上一层有 (j) 个点度数要求为 (2) , (k) 个点度数要求为 (3) ,这层有 (i) 个点时的拼接以及上一层内部连边.

    枚举上一层有 (k) 个点,有 (f(i,j)=sum_{kle i-j}f(i-j,k)cdot g(j,c_2,c_3)) , (c_2,c_3) 表示 (k) 个点中要求度数为 (2,3) 的点,由于它们都各自向父亲连了一条边,实际上还需要连的边数是 (1,2) .

    考虑如何计算转移系数 (g(i,j,k)) .

    • (i>0​) 时,考虑该层第一个点的父亲是哪个点,有

      [g(i,j,k)=jcdot g(i-1,j-1,k)+kcdot g(i-1,j+1,k-1) ]

    • (i=0) 时,此时需要在上一层内互相连边,使得它们满足度数限制,此时再分 (j>0)(j=0) 讨论.

      • (i=0,j>0) 时,枚举第一个还要连 (1) 条边的点连的哪个点,有

        [g(0,j,k)=(j-1)cdot g(0,j-2,k)+kcdot g(0,j,k-1) ]

      • (i=j=0) 时, (k) 个点都要连 (2) 条边,一定是若干个互不相交的,大小 (>2) 的环,这里犯不着 (exp) ,暴力预处理即可.

    最后答案就是 (sum f(n,i)cdot g(0,c_2,c_3)) ,时间复杂度 (O(n^3)) .

    注意根节点没有向父亲连的边,儿子方向上的度数不会 (-1​) ,需要特判一下,即先将前两层的 (f​) 单独算出来.

    CO int N=310;
    int d[N],fac[N],ifac[N];
    int dp[N],g[N][N][N],f[N][N];
    
    IN int C(int n,int m){
    	return mul(fac[n],mul(ifac[m],ifac[n-m]));
    }
    int main(){
    	int n=read<int>();
    	for(int i=1;i<=n;++i) read(d[i]);
    	fac[0]=1;
    	for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    	ifac[n]=fpow(fac[n],mod-2);
    	for(int i=n-1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
    	dp[0]=1;
    	for(int i=3;i<=n;++i)for(int j=3;j<=i;++j)
    		inc(dp[i],mul(dp[i-j],mul(C(i-1,j-1),mul(fac[j-1],i2))));
    	for(int i=0;i<=n;++i)
    		for(int j=0;i+j<=n;++j)for(int k=0;i+j+k<=n;++k){
    			if(i==0){
    				if(j==0) g[i][j][k]=dp[k];
    				else{
    					if(j>=2) inc(g[i][j][k],mul(j-1,g[i][j-2][k]));
    					if(k>=1) inc(g[i][j][k],mul(k,g[i][j][k-1]));
    				}
    			}
    			else{
    				if(j>=1) inc(g[i][j][k],mul(j,g[i-1][j-1][k]));
    				if(k>=1) inc(g[i][j][k],mul(k,g[i-1][j+1][k-1]));
    			}
    		}
    	f[1+d[1]][d[1]]=1;
    	for(int i=d[1]+2;i<=n;++i)for(int j=1;j<=i-(1+d[1]);++j){
    		int c2=0,c3=0;
    		for(int k=1;j+k<=i-1;++k){
    			d[i-j-k+1]==2?++c2:++c3;
    			inc(f[i][j],mul(f[i-j][k],g[j][c2][c3]));
    		}
    	}
    	int ans=0,c2=0,c3=0;
    	for(int i=1;i<=n-1;++i){
    		d[n-i+1]==2?++c2:++c3;
    		inc(ans,mul(f[n][i],g[0][c2][c3]));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    爬虫框架之Scrapy——爬取某招聘信息网站
    爬虫框架之Scrapy
    centos6创建用户,设置ssh登录
    VmWare扩展硬盘分区
    centos安装python与jdk
    vmware安装——CentOS-6.5和Mysql
    python——读取MATLAB数据文件 *.mat
    经纬度坐标互换
    原码, 反码, 补码 详解
    MATLAB——textscan
  • 原文地址:https://www.cnblogs.com/autoint/p/13347831.html
Copyright © 2020-2023  润新知