hdu 5181 numbers——思路+区间DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5181
题解:https://www.cnblogs.com/Miracevin/p/10960717.html
原来卡特兰数的这个问题还能区间DP……
XO
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } const int N=305,M=9e5+5,mod=1e9+7; int n,m,hd[N],xnt,to[M],nxt[M],b[N][N],f[N][N]; bool vis[N]; void init() { memset(b,0,sizeof b); memset(f,0,sizeof f); xnt=0; memset(hd,0,sizeof hd); } void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;} void dfs(int cr) { for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]) { vis[v]=1; b[cr][v]=1; dfs(v); } } bool chk(int x1,int x2,int y1,int y2) { if(x2<x1||y2<y1)return true; int tp=b[x2][y2]-b[x1-1][y2]-b[x2][y1-1]+b[x1-1][y1-1]; return !tp; } void solve() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) b[i][j]+=b[i][j-1]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) b[i][j]+=b[i-1][j]; for(int len=1;len<=n;len++) { for(int i=1;i<=n;i++) { int j=i+len-1; if(j>n)break; f[i][i-1]=f[j+1][j]=1; for(int k=i;k<=j;k++) { if(chk(k,j,i,k-1)&&chk(k,k,k+1,j)) f[i][j]=(f[i][j]+(ll)f[i][k-1]*f[k+1][j])%mod; } } } printf("%d\n",f[1][n]); } int main() { int T=rdn(); while(T--) { init(); n=rdn();m=rdn(); for(int i=1,u,v;i<=m;i++) u=rdn(),v=rdn(),add(u,v); for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); dfs(i); } bool fg=0; for(int i=1;i<=n&&(!fg);i++) for(int j=1;j<=i;j++) if(b[i][j]&&b[j][i]){fg=1;break;} if(fg){puts("0");continue;} solve(); } return 0; }