【省選模擬】20/06/22

AA

  • 令兩類點集合爲 S,TS,T,考慮最後的圖一定形如一堆 S,TS,T 的連通塊以及若干 SS 其中每個 SS 連了若干個 TT,對這個進行 dpdp,記 dpi,jdp_{i,j} 表示兩類點大小下的圖個數,枚舉連通塊轉移,O(n4)O(n^4)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,Mul(a,a)) if(b&1) Mul(as,a); return as; }
cs int N = 105;
int T, n, m, C[N][N], pw[N];
int dp[N][N], f[N][N];
void work(int n){
	for(int i=0; i<=n; i++)C[i][0]=1;
	for(int i=1; i<=n; i++)
	for(int j=1; j<=n; j++)
	C[i][j]=add(C[i-1][j-1],C[i-1][j]);
	pw[0]=1;for(int i=1; i<=n; i++)
	pw[i]=add(pw[i-1],pw[i-1]);
	for(int i=1; i<=n; i++) f[i][0]=1;
	for(int i=1; i<=n; i++)
	for(int j=1; i+j<=n; j++)
	f[i][j]=mul(f[i][j-1],mul(dec(pw[i],1),pw[j-1]));
	for(int i=0; i<=n; i++)
	dp[i][0]=ksm(2,i*(i-1)>>1);
	static int h[N]; h[0]=1;
	for(int i=1; i<=n; i++)
	for(int j=1; j<=i; j++)
	Add(h[i],mul(h[i-j],C[i-1][j-1]));
	for(int i=0; i<=n; i++)
	dp[0][i]=h[i];
	static int z[N]; z[0]=1;
	for(int i=1; i<=n; i++){
		z[i]=dp[i][0];
		for(int j=1; j<i; j++)
		Dec(z[i],mul(C[i-1][j-1],mul(z[j],dp[i-j][0])));
	}
	for(int i=1; i<=n; i++)
	for(int j=1; j<=n; j++)
	Mul(f[i][j],z[i]);
	for(int i=1; i<=n; i++)
	for(int j=1; i+j<=n; j++){
		for(int k=1; k<=i; k++)
		for(int l=1; l<=j; l++)
		Add(dp[i][j],mul(mul(C[i][k],C[j-1][l-1]),mul(dp[i-k][j-l],f[k][l])));
		for(int k=1; k<=j; k++)
		Add(dp[i][j],mul(dp[i][j-k],C[j-1][k-1]));
	}
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	work(100); scanf("%d",&T); while(T--)
	scanf("%d%d",&n,&m), cout<<dp[n-m][m]<<'\n';
	return 0;
}

BB

  • 考慮最後分爲三類點,中間一段的是有貢獻的
    最小割建圖,考慮割與 SS 表示前綴,割 TT 的表示後綴,拆點,割中間的表示在中間
    對於限制,連邊 (a,b),(a,b)(a,b),(a',b') 表示 aa 的段在 bb 之前
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int N = 1e4 + 50;
cs int INF = 1e9 + 7;
int fi[N], nxt[N], to[N], w[N], ec=1;
void adde(int x, int y, int z){
	nxt[++ec]=fi[x], fi[x]=ec, to[ec]=y, w[ec]=z;
	nxt[++ec]=fi[y], fi[y]=ec, to[ec]=x, w[ec]=0;
}
int n, m, a[N], S, T;
int d[N];
bool bfs(){
	memset(d,-1,sizeof(d)); d[S]=0;
	queue<int> q; q.push(S);
	while(!q.empty()){
		int x=q.front(); q.pop();
		for(int e=fi[x],v;e;e=nxt[e])
		if(w[e] && d[v=to[e]]==-1){ 
			d[v]=d[x]+1; q.push(v);
			if(v==T) return true;
		}
	} return false;
}
int dfs(int u, int flw){
	if(u==T) return flw; int ans=0;
	for(int e=fi[u],v;e;e=nxt[e])
	if(d[v=to[e]]==d[u]+1){
		int dlt=dfs(v,min(flw,w[e]));
		w[e]-=dlt; w[e^1]+=dlt;
		ans+=dlt; flw-=dlt; if(!flw) break;
	} if(flw)d[u]=-1; return ans;
}
int dinic(){ int flw=0; while(bfs())flw+=dfs(S,INF); return flw; }
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++)
	scanf("%d",&a[i]);
	S=0, T=n+n+1;
	for(int i=1,u,v; i<=m; i++)
	scanf("%d%d",&u,&v),adde(u,v,INF),adde(u+n,v+n,INF);
	int ans=0;
	for(int i=1; i<=n; i++){
	if(a[i]<0)adde(i,i+n,-a[i]);
	if(a[i]>0)adde(S,i,a[i]),adde(i+n,T,a[i]),ans+=a[i];
	} cout<<ans-dinic()<<'\n';
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章