• [luogu7418]Counting Graphs P


    参考[luogu7417],同样求出最短路,得到二元组$(x,y)$并排序,记$tot_{(x,y)}$为$(x,y)$的数量

    其中所给的两个条件,即分别要求:

    1.$(x,y)$只能和$(xpm 1,ypm 1)$连边

    2.每一个$(x,y)$都向$(x-1,ypm 1)$中的一个连边、$(xpm 1,y-1)$中的一个连边

    (另外,注意在$x+1=y$时$(x+1,y-1)$也即为$(x,y)$自身)

    从前往后依次dp,假设考虑到二元组为$(x,y)$,将之前二元组分为两类——

    (1)对于其中不为$(x,y)$的二元组之后已经不存在能通过连边满足第2个条件的点了,那么就需要保证第2个条件都已经满足,即状态中不需要再记录

    (2)对于二元组$(x,y)$,之后也不存在$(x-1,ypm 1)$的点了,因此$x$的一维必须要已经满足,并记录$y$的一维不满足的数个数即可

    由此,即得到一个二维的状态,将其记为$f_{(x,y),i}$(其中$i$的定义参考(2)中)

    关于转移,有以下四类本质不同的边:

    (1)$(x,y)$与$(x-1,y+1)$中$y$的一维已经满足点的的边

    (2)$(x,y)$与$(x-1,y+1)$中$y$的一维仍未满足的点的边

    (3)$(x,y)$与$(x-1,y-1)$的边

    (4)若$x+1=y$,$(x,y)$和$(x,y)$之间的边

    先转移前两类边(避免出现三维状态),枚举后者的点数,转移即
    $$
    f_{(x,y),i}={tot_{(x,y)}choose i}sum_{j=0}^{tot_{(x-1,y+1)}}G(tot_{(x-1,y+1)},j,tot_{(x,y)}-i)f_{(x-1,y+1),j}
    $$
    (注意此时的$i$的定义并不为最终的定义,仅是一个中间过程)

    其中$G(x,z,y)$表示在左边$x$个点和右边$y$个点连边的$2^{xy}$张图中,满足左边特定的$z$个点(如前$z$个点)和右边的$y$​个点度数均非0的方案数,对左边容斥有
    $$
    G(x,z,y)=sum_{i=0}^{z}(-1)^{i}{zchoose i}(2^{x-i}-1)^{y}
    $$
    再转移第3类边,考虑转移的状态$f_{(x,y),j}$,这$j$个点必须都选择(否则$x$这一维不满足),因此转移即
    $$
    f_{(x,y),i}=sum_{j=0}^{tot_{(x,y)}}{tot_{(x,y)}-jchoose i}(2^{tot_{(x-1,y-1)}}-1)^{tot_{(x,y)}-i}f_{(x,y),j}
    $$
    (这里是类似于01背包的,即后者$f_{(x,y),j}$应该是未转移第3类边的结果)

    最后转移第4类边,其实这只是一个特例,更完整的情况应该是对于$(x+1,y-1)$不再出现的点(即其之后不再参与转移,之后也没有点可以帮助其满足第2个条件)将其的贡献乘到答案上

    具体的,这类状态又分为两类:

    1.$x+1 e y$,这类状态不能通过自环使其满足条件,因此贡献即$f_{(x,y),0}$

    2.$x+1=y$,这还可以通过自环使其满足条件

    具体的,贡献即$sum_{i=0}^{tot_{(x,y)}}G(tot_{(x,y)},i)f_{(x,y),i}$,其中$G(x,y)$表示在$x$个点中任意连边的$2^{frac{x(x+1)}{2}}$张图中(允许自环),满足特定的$y$个点度数均非0的方案数,对这$y$​个点容斥有
    $$
    G(x,y)=sum_{i=0}^{y}(-1)^{i}{ychoose i}2^{frac{(x-i)(x-i+1)}{2}}
    $$
    不难发现$f$的状态数实际仅为$o(n)$,转移复杂度为$o(n^{2})$,总复杂度即$o(n^{3})$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 105
      4 #define M 10005
      5 #define mod 1000000007
      6 #define oo 0x3f3f3f3f
      7 #define ll long long
      8 struct Edge{
      9     int nex,to;
     10 }edge[M*3];
     11 queue<int>q;
     12 int t,n,m,E,x,y,ans,mi[M],Mi[N][N],C[N][N],head[N<<1],d[N<<1],tot[N][N],g[N],f[N];
     13 void add(int x,int y){
     14     edge[E].nex=head[x];
     15     edge[E].to=y;
     16     head[x]=E++;
     17 }
     18 int G(int x,int y){
     19     int ans=0;
     20     for(int i=0;i<=y;i++){
     21         int s=(ll)C[y][i]*mi[(x-i)*(x-i+1)/2]%mod;
     22         if (i&1)ans=(ans-s+mod)%mod;
     23         else ans=(ans+s)%mod;
     24     }
     25     return ans;
     26 }
     27 int G(int x,int z,int y){
     28     int ans=0;
     29     for(int i=0;i<=z;i++){
     30         int s=(ll)C[z][i]*Mi[x-i][y]%mod;
     31         if (i&1)ans=(ans-s+mod)%mod;
     32         else ans=(ans+s)%mod;
     33     }
     34     return ans;
     35 }
     36 int main(){
     37     mi[0]=1;
     38     for(int i=1;i<M;i++)mi[i]=2*mi[i-1]%mod;
     39     for(int i=0;i<N;i++){
     40         Mi[i][0]=1;
     41         for(int j=1;j<N;j++)Mi[i][j]=(ll)Mi[i][j-1]*(mi[i]-1)%mod;
     42     }
     43     for(int i=0;i<N;i++){
     44         C[i][0]=C[i][i]=1;
     45         for(int j=1;j<i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
     46     }
     47     scanf("%d",&t);
     48     while (t--){
     49         scanf("%d%d",&n,&m);
     50         E=0,ans=1;
     51         memset(head,-1,sizeof(head));
     52         memset(d,oo,sizeof(d));
     53         memset(tot,0,sizeof(tot));
     54         for(int i=1;i<=m;i++){
     55             scanf("%d%d",&x,&y);
     56             add(x,y+n),add(y+n,x);
     57             add(x+n,y),add(y,x+n);
     58         }
     59         d[1]=0;
     60         q.push(1);
     61         while (!q.empty()){
     62             int k=q.front();
     63             q.pop();
     64             for(int i=head[k];i!=-1;i=edge[i].nex)
     65                 if (d[edge[i].to]==oo){
     66                     d[edge[i].to]=d[k]+1;
     67                     q.push(edge[i].to);
     68                 }
     69         }
     70         if (d[n+1]==oo){
     71             for(int i=1;i<=n;i++)tot[0][min(d[i],d[i+n])]++;
     72             for(int i=1;i<=n;i++)ans=(ll)ans*Mi[tot[0][i-1]][tot[0][i]]%mod;
     73             printf("%d
    ",ans);
     74             continue;
     75         }
     76         for(int i=1;i<=n;i++)tot[d[i]+d[i+n]-d[n+1]>>1][min(d[i],d[i+n])]++;
     77         for(int x=0;x<=n;x++){
     78             memset(f,0,sizeof(f));
     79             f[0]=1;
     80             for(int y=x;y<=n;y++){
     81                 if (!tot[x][y]){
     82                     if (y-x<=(d[n+1]>>1))ans=(ll)ans*f[0]%mod;
     83                     else{
     84                         int s=0;
     85                         for(int i=0;i<=tot[x][y-1];i++)s=(s+(ll)G(tot[x][y-1],i)*f[i])%mod;
     86                         ans=(ll)ans*s%mod;
     87                     }
     88                     memset(f,0,sizeof(f));
     89                     f[0]=1;
     90                     continue;
     91                 }
     92                 if ((!x)&&(!y)){
     93                     f[0]=0,f[1]=1;
     94                     continue;
     95                 }
     96                 memcpy(g,f,sizeof(g));
     97                 memset(f,0,sizeof(f));
     98                 for(int i=0;i<=tot[x][y];i++){
     99                     int s=0;
    100                     for(int j=0;j<=tot[x][y-1];j++)s=(s+(ll)G(tot[x][y-1],j,tot[x][y]-i)*g[j])%mod;
    101                     f[i]=(f[i]+(ll)C[tot[x][y]][i]*s)%mod;
    102                 }
    103                 memcpy(g,f,sizeof(g));
    104                 memset(f,0,sizeof(f));
    105                 if (!x){
    106                     f[tot[x][y]]=g[0];
    107                     continue;
    108                 }
    109                 for(int i=0;i<=tot[x][y];i++)
    110                     for(int j=0;j<=tot[x][y];j++)f[i]=(f[i]+(ll)C[tot[x][y]-j][i]*Mi[tot[x-1][y-1]][tot[x][y]-i]%mod*g[j])%mod;
    111             }
    112         }
    113         printf("%d
    ",ans);
    114     }
    115     return 0;
    116 } 
    View Code
  • 相关阅读:
    python 三方面库整理
    windows MYSQL 安装及修改root密码
    TCP 套叠字
    自动化谷歌浏览驱动
    python os
    python 协程
    python GIL :全局解释器
    python 多进程
    python 多线程
    python 3 往Excel 中的写入内容但不覆盖原内容
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15195822.html
Copyright © 2020-2023  润新知