专栏文章

题解:CF888F Connecting Vertices

CF888F题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miqdovni
此快照首次捕获于
2025/12/04 03:06
3 个月前
此快照最后确认于
2025/12/04 03:06
3 个月前
查看原文

Solution

显然要断环成链。我们要计算出 fl,rf_{l,r} 表示 llrr 联通的方案数。
如果 llrr 之间需要有连边,则将它删掉之后,区间 [l,r][l,r] 中的点恰好分为两个连通块;如果没有连边,我们可以找到最大的 uu 使得 uurr 有连边,这样拆分成 [l,u][l,u] 联通与 [u,r][u,r] 联通。
我们发现,还是要记录 llrr 有连边的方案数,设为 gl,rg_{l,r}
因此转移就是:
gl,r=al,rt=lr1fl,tft+1,rg_{l,r} = a_{l,r} \sum_{t=l}^{r-1} f_{l,t}f_{t+1,r}
以及
fl,r=gl,r+u=l+1r1fl,ugu,rf_{l,r} = g_{l,r} + \sum_{u=l+1}^{r-1} f_{l,u}g_{u,r}
答案就是 f1,nf_{1,n}
CPP
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=500+10,MOD=1e9+7;
int n,a[MAXN][MAXN],f[MAXN][MAXN],g[MAXN][MAXN];
signed main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n;
	ffor(i,1,n) ffor(j,1,n) cin>>a[i][j];
	ffor(i,1,n) f[i][i]=1;
	ffor(len,2,n) for(int l=1,r=len;r<=n;l++,r++) {
		if(a[l][r]) ffor(t,l,r-1) g[l][r]=(g[l][r]+f[l][t]*f[t+1][r])%MOD;
		f[l][r]=g[l][r];
		ffor(u,l+1,r-1) f[l][r]=(f[l][r]+f[l][u]*g[u][r])%MOD;
	}
	cout<<f[1][n];
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...