zoukankan      html  css  js  c++  java
  • POJ 1737 经典DP

    问题:求含有n个点的连通图的个数。

    解:

      考虑DP,$f(n)$表示n个点,每个点都和点1相连,且n个点互相连通的图的个数。

      (蓝字非常重要,这个条件有效地避免了重复计算

           $g(n)$表示n个点,每个点都和点1相连,且不是n个点互相连通的图的个数。

           $S(n)$表示n个点的图的个数。

    显然,有:$f(n) = S(n)-g(n)$

         $S(n) = 2^{n(n-1)/2}$

    而且有(关键):$g(n) = sum_{i=1}^{n-1}{C_{n-1}^{i-1} * f(i) * S(n-i)}$

      从除了1之外的n-1个点中选出i-1个点,让这i个点互相连通,而剩下的n-i个点和这i个点没有边相连,互相之间随意连接。

    当然,博主并不想写高精度

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 #define LL long long
     6 #define N 61
     7 
     8 using namespace std;
     9 
    10 LL f[N],g[N];
    11 LL C[N][N];
    12 const int n=50;
    13 
    14 LL S(int x){
    15     if(x==0) return 0;
    16     return (1LL<<( (x*(x-1)) /2));
    17 }
    18 
    19 int main(){
    20     f[1]=1; g[1]=0;
    21     C[0][0]=1;
    22     for(int i=1;i<=n;i++){
    23         C[i][0]=1;
    24         for(int j=1;j<=i;j++)
    25             C[i][j]=C[i-1][j-1]+C[i-1][j];
    26     }
    27     for(int i=2;i<=n;i++){
    28         g[i]=0;
    29         for(int j=1;j<i;j++)
    30             g[i] = g[i] + (C[i-1][j-1]*f[j]*S(i-j));
    31         f[i]=S(i)-g[i];
    32     }
    33     int x;
    34     while(cin>>x,x) cout<<f[x]<<endl;
    35     return 0;
    36 }
    View Code

    接下来是多校联盟中有关于本题的拓展:

    问题:求左侧n个点,右侧m个点的联通二分图个数

    解:参照上面的解法。

      $f(i,j)$表示左面i个点右面j个点,每个点都和左面的点1相连,且n个点互相连通的图的个数。

      $g(i,j)$表示左面i个点右面j个点,每个点都和左面的点1相连,且n个点不是互相连通的图的个数。

      $S(i,j)$定义类比上面。

     和上面一样的,有:

    $f(n,m)=S(n,m)-g(n,m)$

    $S(n,m)=2^{nm}$

    $g(n,m)=sum_{r=1}^{n-1}{ sum_{s=1}^{m-1}{ C_{n-1}^{r-1}*C_{m}^{s}*f(r,s)*S(n-r,m-s)    } }$

  • 相关阅读:
    python-Beautiful rose
    python-and和 or用法
    myspl数据库基础
    python 协程
    python-os 模块
    python-logging模块
    异常处理
    面向对象-类中的三个装饰器
    Flask初见
    django中的ContentType使用
  • 原文地址:https://www.cnblogs.com/lawyer/p/5700968.html
Copyright © 2011-2022 走看看