zoukankan      html  css  js  c++  java
  • 图论--连通二分图计数

    问题:含有两边分别为 n 和 m 个不同的点的连通二分图有多少种,即同构的图算是多个。

    记 含有 n , m 个点的连通图个数为 F[n][m] ;

      含有 n , m 个点的不连通图个数为 G[n][m] ;

      含有 n , m 个点的图的个数为 H[n][m] = 2^(n*m) ;

      有  F[n][m] + G[n][m] = H[n][m] ;  F[n][m] = H[n][m] - G[n][m] ;

    因此要求 F[n][m] 只需求 G[n][m] ;

    求 G[n][m] :枚举 1 号点所在的连通块大小为 k1 ( 1 ~ n ) + k2 ( 0 ~ m ) 且 k1、k2 不能同时取最大值;

           当 1 号点所在连通块大小为 k1+k2 时: k1个点选取情况为组合数  C[n-1][k1-1]

                              k2个点选取情况为组合数  C[m][k2]

                              该连通块的种类数确定 k1+k2 个点后,连通块的种类数为 F[k1][k2] 

                              剩余 n-k1 + m-k2 个点组成的图的种类数 H[n-k1][m-k2]

                              因此情况数为 C[n-1][k1-1] * C[m][k2] * F[k1][k2] * H[n-k1][m-k2]

         G[n]为所有枚举的情况数总和

    定初始值 F[0][0] = F[0][1] = F[1][0] = 1 , 其余有一维是 0 时 F 值为 0

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<math.h>
     5 using namespace std;
     6 typedef long long ll;
     7 
     8 const int maxn=55;
     9 const int maxm=55;
    10 const int mod=1e9+7;
    11 
    12 ll C[maxn][maxn];        //组合数
    13 ll F[maxn][maxm],G[maxn][maxm],H[maxn][maxm];
    14 
    15 ll QP(ll a,ll n){        //快速幂
    16     ll tmp=a,ans=1;
    17     while(n){
    18         if(n&1)ans=ans*tmp%mod;
    19         tmp=tmp*tmp%mod;
    20         n>>=1;
    21     }
    22     return ans;
    23 }
    24 
    25 void init(){
    26     for(int i=0;i<maxn;++i){
    27         for(int j=0;j<maxm;++j){
    28             H[i][j]=QP(2,i*j);
    29         }
    30     }
    31     for(int i=0;i<maxn;++i){
    32         for(int j=0;j<=i;++j){
    33             C[i][j]=(i&&j)?(C[i-1][j]+C[i-1][j-1])%mod:1;
    34         }
    35     }
    36     F[0][0]=F[1][0]=F[1][0]=1;
    37     for(int i=2;i<maxn;++i)F[i][0]=0;
    38     for(int i=2;i<maxm;++i)F[0][i]=0;
    39     for(int i=1;i<maxn;++i){
    40         for(int j=1;j<maxm;++j){
    41             G[i][j]=0;
    42             for(int k1=1;k1<=i;++k1){
    43                 for(int k2=0;k2<=j;++k2){
    44                     if(k1==i&&k2==j)continue;
    45                     G[i][j]+=C[i-1][k1-1]*C[j][k2]%mod*F[k1][k2]%mod*H[i-k1][j-k2]%mod;
    46                     G[i][j]%=mod;
    47                 }
    48             }
    49             F[i][j]=((H[i][j]-G[i][j])%mod+mod)%mod;
    50         }
    51     }
    52 }
  • 相关阅读:
    Android设计模式(三)--装饰模式
    kmp算法总结
    SDWebImage源代码解析(二)
    关于C++构造函数一二
    逆向随笔
    iOS中的crash防护(二)KVC造成的crash
    git-osc自己定义控件之:CircleImageView
    java中继承关系学习小结
    openwrt针对RT5350代码下载,配置和编译
    MySQL监控
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/5688549.html
Copyright © 2011-2022 走看看