ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[luogu7418]Counting Graphs P

2021-08-28 07:00:14  阅读:247  来源: 互联网

标签:连边 个点 sum tot Graphs luogu7418 Counting 转移 pm


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

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

1.$(x,y)$只能和$(x\pm 1,y\pm 1)$连边

2.每一个$(x,y)$都向$(x-1,y\pm 1)$中的一个连边、$(x\pm 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,y\pm 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}{z\choose 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)}-j\choose 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\ne 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}{y\choose 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\n",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\n",ans);
114     }
115     return 0;
116 } 
View Code

 

标签:连边,个点,sum,tot,Graphs,luogu7418,Counting,转移,pm
来源: https://www.cnblogs.com/PYWBKTDA/p/15195822.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有