·最小割和组合数放在了一起,产生了这道题目

英文题,述大意;
     一张初始化为仅有一个起点0,一个终点1和一条边的图。输入n,m表示n次操作(1<=n,m<=50),每次操作是任选一条已存在的边,新建一个编号为(n+1)的节点并向这条边的两个端点连边(共连接两条边)。输入n次操作后满足最小割为m的图有多少种。此处两个图相同当且仅当两边集和点集满足双射。答案取模109+7。

分析:

     本题要求方案数。首先读题较困难之处是什么样的两个图算不同的方案。知道每次加入的点是有编号的,有编号的点是独一无二的。在这里画一些图以便清晰理解,以下两个图的情况均为两种方案而不是一种:

      回到题目要求,最苛刻的无非是加入了最小割的限制。因此先试放宽要求,不考虑最小割的限制。那么,假如当前进行了n次操作,那么图中的边数可以算出来等于(1+2*n),那么第(n+1)次操作所添加的点共有(1+2*n)种添加方式。没有最小割,这个思路将非常棒。

      但是你可以发现,如果添上最小割,上述方法就不可行了。分析失败的原因:每次添加一个点到随意地一个位置的方法难以维护当前图的最小割。因此,我们需要寻找一种方法,既可以通过组合计算方案数(因为这道题不可能枚举每种图,所以计算组合方案是必要的)又可以保证能够在保持最小割为某个值的情况下进行方案数运算。   

      对于上述需求,我们可以想到,为了能够保持某些性质(最小割),可以通过枚举子问题来实现。所谓子问题就是将原来的问题化成几个规模较小的但是形式和性质相同的问题加以解决(如动态规划利用了子问题的性质)。

     本题的图怎样拆成子问题呢?入手点可以选择为最早的点数为3的图。我们发现,这个点数为3的图可以由这些部分组成:

这里面已经有了子问题的影子。观察任意一条新添边和其两端点组成的子图,其实就是操作数为0的时候的图(即只有起点终点的图),也就是说,我们正尝试把当前图拆为一条主干边及两端点和一些操作数较小的子图。我们来欣赏这个样例吧:

   为什么偏要分成两部分?原因是可以快速维护最小割。该图的最小割就等于min{子问题1图的最小割,子问题2图的最小割}。我们可以将这样一对子问题看成在主干边上建一座大桥。我们知道主干边上是可以建很多座大桥的:

     图为三座大桥。当多座桥存在的时候,最小割的计算方式为每座桥的最小割相加。得到这个结论后可以发现,一个图由主干边加很多桥组成,由于图的点数大于这些桥的点数,因此从点数由小到大的递推状态转移具有可行性。

     想想递推求方案数。令:

     f[i][j]表示当前进行了i次操作(即有(i+2)个点),图的最小割为j的种类数

     g[i][j]表示当前进行了i次操作,最小割为j的大桥的种类数

     这个状态看上去g[i][j]是专门为f[i][j]服务的。那好吧就先这样认为吧,因为上文讲的内容全是用各种各样的桥构造当前图。先别急桥怎么处理,不过要记住一点:一个桥的本质是一个子问题二元组(见上文桥的来源就知道了)。

     首先想一个填表式的伪状态转移方程:

      f[这个大大的图]+=f[这个大大地图-某座桥]*g[这桥]

    画图可以表示为:

      接下来我们一步步细化方程式。设图的操作数为i,最小割为j。

[第一步]将上式子转化为较为正统的方程式:

      设枚举的桥操作数为i,最小割为j。

             f[x][y]+=f[x-i][x-j]*g[i][j]

[第二步]由于同种桥可以添加多次,所以完善方程式:
      设当前操作数为i,最小割为j的桥将被使用T次。

             f[x][y]+=f[x-i*T][y-j*T]*MultiCombination(g[i][j],T)

      我们知道操作数为i,最小割为j的桥共有g[i][j]种,此处我们要从中选出T座桥,由于相同桥可以多次选择,因此问题转化为在g[i][j]中选出T个桥,一个桥可以被多次选择的方案数,即MultiCombination,其值等于C(g[i][j]+T-1,T)

[第三步]为了做到能够边转移边递推多重组合(MC),将方程转为刷表法:

      设当前操作数为i,最小割为j的桥将被使用T次。

             f[x+i*T][y+j*T]+=f[i][j]*MultiCombination(g[i][j],T)

      转化形式的好处就是我们可以顺次枚举T,那么可以使用一个comb来表示当前C(g[i][j]+T-1,T)的值,若T变为(T+1),那么可以直接递推:

             comb=comb*(g[i][j]+T)/T

[合法性证明]刷表法到达i,j的时候,由于小于i,j的子问题已经贡献了答案,因此此时f[i][j]已经是正确方案数,用它来更新更大的状态不会造成遗漏。

      至此,我们已经成功地借助g[][]完成了对f[][]的递推。该想想g[i][j]怎么求了。我们回到最初,看看桥是什么东西——桥指的是两个满足条件的图A,B并且对于当前的大图,其中一个图和这个大图起点重合,另一个图和这个大图终点重合,然后第一个图的终点和第二个图的起点重合:(回顾一下吧)

然后就很奇妙:我们发现两个子问题图的操作数一定小于大图的操作数,也就是说满足从大到小的关系——小图的f[][]不已经求出来了吗?因此桥是需要由组成它的两个子图来计算方案数的。在本文开始的时候提到过怎么样的两个图算是不同,这里我们计算g[i][j]的方法是,先固定左边的子问题图的最小割等于j,然后右边的图最小割随意为多少,并且保证两个图的操作数加起来等于i-1(-1的原因画图可知),然后左右反过来进行一次:    

      g[i][j]+=f[a][j]*f[i-1-b][u] (u>=j)

      g[i][j]+=f[a][u]*f[i-1-b][j] (u> j)

     总结来说,本题的核心在于寻找子问题从而求解方案数,同时结合了本题的加边特点维护最小割。代码在这里:    

 #include<stdio.h>
#include<cstring>
#define ll long long
#define M 1000000007
#define go(i,a,b) for(int i=a;i<=b;i++)
const int N=;int n,m;
ll f[N][N],g[N][N],t[N][N],INV[N];
int main()
{
scanf("%d%d",&n,&m);f[][]=;
INV[]=;go(i,,)INV[i]=(-M/i*INV[M%i])%M; go(i,,n)go(j,,i+)
{
go(a,,i-){int b=i--a;
go(u, j ,a+)(g[i][j]+=f[a][u]*f[b][j])%=M;
go(u,j+,b+)(g[i][j]+=f[a][j]*f[b][u])%=M;} memset(t,,sizeof(t)); go(x,,n)go(y,,x+){ll comb=;
go(T,,n){if(x+T*i>n)break;
(comb*=(g[i][j]+T-)%M*INV[T]%M)%=M;
(t[x+i*T][y+j*T]+=comb*f[x][y]%M)%=M;}} go(x,,n)go(y,,x+)(f[x][y]+=t[x][y])%=M; }
printf("%d",(f[n][m]%M+M)%M);return ;
}//Paul_Guderian

  

   

 

   

    

 

A never-ending, fast-changing and dream-like world unfolds,

as the secret door opens…… ——————本题题干节选

【Codeforces Round #431 (Div. 1) D.Shake It!】的更多相关文章

  1. 【Codeforces Round 431 (Div. 2) A B C D E五个题】

    先给出比赛地址啦,感觉这场比赛思维考察非常灵活而美妙. A. Odds and Ends ·述大意:      输入n(n<=100)表示长度为n的序列,接下来输入这个序列.询问是否可以将序列划 ...

  2. 【Codeforces Round #431 (Div. 2) A】Odds and Ends

    [链接]点击打开链接 [题意] 让你把一个数组分成奇数个部分. 且每个部分的长度都是奇数. [题解] 很简单的脑洞题. 开头和结尾一定要为奇数,然后 n为奇数的话,就选整个数组咯. n为偶数的话,不能 ...

  3. 【Codeforces Round #431 (Div. 2) B】 Tell Your World

    [链接]点击打开链接 [题意] n个点,x从左到右严格递增的顺序给出 让你划两条平行的,且没有相同点的直线; 使得它们俩各自最少穿过一个点. 且它们俩穿过了所有的点. [题解] 枚举第一个点和哪个点组 ...

  4. 【Codeforces Round #431 (Div. 2) C】From Y to Y

    [链接]点击打开链接 [题意] 让你构造一个大小最多为10W的字符multiset. 你进行n-1次操作; 每次操作,从set中取出两个字符串,一开始单个字符被认为是字符串. 然后把它们连接在一起. ...

  5. 【Codeforces Round #431 (Div. 1) B】

    [链接]h在这里写链接 [题意] 场上有 n 个点,它们分别向上与向右在不同时刻开始运动,相遇则改变移动方向,求最终这些点到达的坐标. [题解] 先把每个点的坐标都往它本该移动的方向相反的方向退ti个 ...

  6. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] C】Greedy Arkady

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举那个人收到了几次糖i. 最好的情况显然是其他人都只收到i-1次糖. 然后这个人刚好多收了一次糖 也即 (i-1)kx + x & ...

  7. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] E】Short Code

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先建立一棵字典树. 显然,某一些节点上会被打上标记. 问题就转化成求所有标记的深度的和的最小值了. (标记可以上移,但是不能在同一位 ...

  8. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] D】Single-use Stones

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 设长度为L的所有区间里面,石头的个数的最小值为k 设取到k的区间为l,r 那么k就为最多能通过的青蛙个数. 假设k再大一点.比如为k ...

  9. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] A】Paper Airplanes

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 统计每个人需要的sheet个数. 乘上k 然后除p就是需要的pack个数了 [代码] #include <bits/stdc+ ...

随机推荐

  1. Scrum 冲刺 第一日

    Scrum 冲刺 第一日 站立式会议 燃尽图 Alpha 阶段认领任务 明日任务安排 项目预期任务量 成员贡献值计算规则 今日贡献量 参考资料 站立式会议 返回目录 燃尽图 返回目录 Alpha 阶段 ...

  2. java连接jdbc Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by defa

    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsp_db","root",& ...

  3. javascript抛物投栏(抛物线实践)

    平面内,到定点与定直线的距离相等的点的轨迹叫做抛物线.水平抛物线就是水平匀速,垂直加速的运动. 抛物线的性质:面内与一个定点F和一条定直线l 的距离相等的点的轨迹叫做抛物线. 定点F叫做抛物线的焦点. ...

  4. 18-TypeScript模板方法模式

    在有些情况下,一个功能在基础功能上是不会变的,算法的基本骨架也是确定的,但是在某些场景下算法的具体实现有些差异.应对这种问题,可以采用模板方法模式: abstract class Salary{ ab ...

  5. Mego开发文档 - 数据属性生成值

    数据属性生成值 该功能用于在数据插入或更新时为指定属性生成期望的值,Mego提供了非常灵活的实现方式以满足各种数据提交时的自动赋值问题. 生成值目的及模式 在Mego中生成值的目的一定是插入数据或更新 ...

  6. tomcat-theory

    (一) java类:applet,servlet,jsp JSP:.jsp-->.java-->(JVM).classJDK:javac,.java-->.classweb:Serv ...

  7. c++中模板是什么?为什么要定义模板?

    一.c++中模板是什么? 首先: int Max(int x, int y) { return x > y ? x : y; } float Max(float a,float b) { ret ...

  8. 赛码网算法: 上台阶 ( python3实现 、c实现)

    上台阶 题目描述 有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第m级,共有多少走法?注:规定从一级到一级有0种走法. 输入输入数据首先包含一个整数n(1<=n<=1 ...

  9. [转]安卓新一代多渠道打包工具Walle 解决渠道包V2签名问题

    转自https://www.jianshu.com/p/572b59829a08 为什么要打多个渠道的包? 大家都知道,android应用商店大大小小有几百个,作为一个有志向的app,就需要做到统计各 ...

  10. Mysql中给有记录的表添加唯一索引

    ALTER IGNORE TABLE neeqs ADD UNIQUE KEY `unique` (`seccode`, `enddate`, `f002v`);