版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/81318629
折磨了一天想办法处理怎么用出度序列判断合法性,绝望的时候,同学说:
“这不是竞赛图么?”
“。。。。。。“
Landau’s Theorem:
当出度序列按非递减排序后前
个的和不小于
即合法。不会证。
直接dp就完事了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
//Container--
//
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
const ll md=1e9+7;ll cb[41][41],dp[2][41][1600];int tr[41];
inline int _x(int n){return n*(n-1)/2;};
void _init(){
int i,j,k,d,t;for(i=0;i<=40;++i)for(cb[i][0]=1,j=1;j<=i;++j)
cb[i][j]=(cb[i-1][j-1]+cb[i-1][j])%md;
};
void cl(){
int i,j,k,d,t,n,dn,a,b,ps,pc;for(scanf("%d",&n),clr(tr),dn=i=0;i<n;++i){
scanf("%d",&t);
if(t<0)++dn;
else
tr[t]++;
}
for(clr(dp),ps=pc=0,b=1,dp[a=0][0][0]=1,i=0;i<n;++i){
for(clr(dp[b]),j=pc;j<=pc+dn;++j)for(k=ps;k<=_x(n);++k)if(dp[a][j][k]){
for(d=0;d<=dn-j+pc;++d){
if(k+(tr[i]+d)*i<_x(j+tr[i]+d))continue;
dp[b][j+tr[i]+d][k+(tr[i]+d)*i]+=(dp[a][j][k]*cb[dn-(j-pc)][d]%md);
dp[b][j+tr[i]+d][k+(tr[i]+d)*i]%=md;
}
}
ps+=tr[i]*i,pc+=tr[i];
swap(a,b);
}
printf("%lld\n",dp[a][n][_x(n)]);
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;scanf("%d",&t);for(_init();t--;cl());
return 0;
};