zoukankan      html  css  js  c++  java
  • 带边数的无向连通图计数

    就是求 (n) 个点 (m) 条边的带标号无向连通图个数。

    首先可以用最暴力的 (O(n^6)) 做法,直接按城市规划一题的容斥 DP 做法,
    (f_{n,m}) 表示答案,可以枚举 (1) 号点所在块的情况容斥计算。

    (O(n^4)) 做法是一个有意思的斯特林反演。

    考虑一个选了 (m) 条边的方案,且形成 (k) 个连通块方案块的方案是 (F_{m,k})
    现在我们还是 (m) 条边,但人为划分出来 (j) 个块一定不两两相连,但块内任意连边,方案是 (G_{m,j})

    有组合关系:

    [G_{m,k} = sum_{jge k} S2(j, k) F_{m,j} ]

    反演以后即:

    [F_{m,k} = sum_{jge k} S1(j, k) (-1)^{j - k} G_{m,j} ]

    我们要求的即:

    [F_{m,1} = sum_{jge 1} (j - 1)! (-1)^{j - 1} G_{m,j} ]

    考虑 DP 后面那个 (G),暴力大概不止 (O(n^6))
    但是我们发现算这个 (G) 只需要知道块的划分情况,那么这 (m) 条边的可以随意选取。
    (H_{i,j,m}) 表示 DP 了 (i) 个点,分了 (j) 个块,当前共有 (m) 个边可以用的方案数。

    则有:

    [G_{m,j}=sum_{kge m} H_{n,j,k} {kchoose m} ]

    直接 DP 这个 H 复杂度过高,接下来尝试缩去中间 (j) 那一维。
    现在考虑把 ((j - 1)! (-1)^{j - 1}) 的附加贡献在 DP 过程中算上,
    发现我们可以先正常选一个块,并固定这个块的一号在最前面,
    然后剩下的每加入一个块,带一个 (-1) 的系数并且把这个块的点任意插进去(只需保证不在开头,系数 (i + k - 1choose k))进行 DP。
    这样就做到让一个 (k) 个块的方案会算重 ((k - 1)!) 次。
    时间复杂度 (O(n^4))

    然而代码短小精悍。

    void DP()
    {
    	for(int i = 1; i <= n; ++i)
    		H[i][c2(i)] = 1;
    	for(int i = 1; i <= n; ++i)
    		for(int j = c2(i); j >= 0; --j)
    			if(H[i][j])
    				for(int k = 1; i + k <= n; ++k)
    					H[i + k][j + c2(k)] = (H[i + k][j + c2(k)] - 1ll * H[i][j] * C[i + k - 1][k]) % mod;
    	for(int j = 0; j <= c2(n); ++j)
    	{
    		for(int k = j; k <= c2(n); ++k)
    			F[j] = (F[j] + 1ll * H[n][k] * C[k][j]) % mod;
    		F[j] = (F[j] + mod) % mod;
    		printf("%d
    ", F[j]);
    	}
    }
    
  • 相关阅读:
    selennium模块
    urllib模块
    有关爬虫模块
    爬虫_requests_html
    爬虫x_path
    项目上线
    navicat使用 pymysql操作数据库 sql注入及增删改查
    基本查询语句和方法,连表,子查询
    表与表之间的关系
    存储引擎 数据类型
  • 原文地址:https://www.cnblogs.com/bestwyj/p/13052448.html
Copyright © 2011-2022 走看看