[HDU 5729] Rigid Frameworks (二分图联通方案计数)

HDU - 5729

给定一个 N*M的矩形格子,问在一个格子里只添加一条斜线,
将整个图形变成一个刚性的图形的方案数有多少种


根据 Project Euler 434,问题可以转化为
一个左边有 N 个点,右边有 M个点的二分图的联通方案计数
首先对于一个 NM 的格子图,每个格子要么不加,
要么向左加一条斜线,要么向右加一条斜线,所以总方案数 2NM
接下来扣去其中不合法的方案数

dp[n][m] 为左边 n 个点,右边 m个点的方案数
对于左边的某一个点(不妨设为 1 号点),
如果它不与图中其他所有点同在一个联通分量,那么就是不合法的
设从左边选 i个点,右边选 j 个点与 1在同一个联通分量
剩下的 n1i mj 个点随意连接
方案数为 C(n1,i)C(m,j)dp[i+1][j]3(n1i)(mj)
所以枚举 i j减去即可
dpn,m=3nmi=0,j=0i<=n1,j<=mCin1Cjmdpi+1.j3(n1i)(mj)

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("----------")

const int MOD=1e9+7;
int N,M;
LL dp[20][20];
LL pow3[110];
LL C[20][20];

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    #endif

    pow3[0]=1;
    for(int i=1; i<=100; i++) pow3[i] = pow3[i-1]*3%MOD;
    for(int i=0; i<=10; i++)
    {
        C[i][0]=1;
        for(int j=1; j<=i; j++) C[i][j] = (C[i-1][j] + C[i-1][j-1])%MOD;
    }

    for(int n=0; n<=10; n++) for(int m=0; m<=10; m++)
    {
        dp[n][m] = pow3[n*m];
        for(int i=0; i<=n-1; i++)
        {
            for(int j=0; j<=m; j++)
            {
                if(i==n-1 && j==m) break;
                dp[n][m] = (dp[n][m] - C[n-1][i]*C[m][j]%MOD * pow3[(n-1-i)*(m-j)]%MOD * dp[i+1][j] )%MOD;
            }
        }
        dp[n][m] = (dp[n][m]+MOD)%MOD;
    }

    while(~scanf("%d%d", &N, &M)) printf("%lld\n", dp[N][M]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值