[CQOI2009]DANCE跳舞(ISAP写法)
https://daniu.luogu.org/problemnew/show/3153
#include<queue> #include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 2501 #define M 3001 #define inf 2e9 int n,k; char s[51]; bool mp[51][51]; int tot; int front[N],to[M<<1],nxt[M<<1],val[M<<1],from[M<<1]; int src,decc; int cur[N]; int path[N],num[N],lev[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void add(int u,int v,int w) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w; from[tot]=u; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=0; from[tot]=v; //cout<<u<<' '<<v<<'\n'; } void rebuild(int mid) { tot=1; memset(front,0,sizeof(front)); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(mp[i][j]) add(i,n*3+j,1); else add(n+i,n*2+j,1); for(int i=1;i<=n;++i) add(src,i,mid); for(int i=1;i<=n;++i) add(n*3+i,decc,mid); for(int i=1;i<=n;++i) add(i,n+i,k); for(int i=1;i<=n;++i) add(n*2+i,n*3+i,k); } bool bfs() { queue<int>q; for(int i=src;i<=decc;++i) lev[i]=decc; q.push(decc); lev[decc]=0; int now,t; while(!q.empty()) { now=q.front(); q.pop(); for(int i=front[now];i;i=nxt[i]) { t=to[i]; if(lev[t]==decc && val[i^1]) { lev[t]=lev[now]+1; q.push(t); } } } return lev[src]!=decc; } int augment() { int now=decc,flow=inf; int i; while(now!=src) { i=path[now]; flow=min(flow,val[i]); now=from[i]; } now=decc; while(now!=src) { val[path[now]]-=flow; val[path[now]^1]+=flow; now=from[path[now]]; } return flow; } int max_flow(int mid) { int flow=0; if(!bfs()) return 0; memset(num,0,sizeof(num)); for(int i=src;i<=decc;++i) num[lev[i]]++,cur[i]=front[i]; int now=src; int t; while(lev[src]<=decc) { if(now==decc) { flow+=augment(); now=src; } int advanced=false; for(int i=cur[now];i;i=nxt[i]) { t=to[i]; if(val[i]>0 && lev[t]==lev[now]-1) { advanced=true; path[t]=i; cur[now]=i; now=t; break; } } if(!advanced) { int m=decc-1; for(int i=front[now];i;i=nxt[i]) if(val[i]>0) m=min(m,lev[to[i]]); if(!--num[lev[now]]) break; num[lev[now]=m+1]++; cur[now]=front[now]; if(now!=src) now=from[path[now]]; } } return flow; } bool check(int mid) { rebuild(mid); return max_flow(mid)==n*mid; } int main() { read(n); read(k); decc=n*4+1; for(int i=1;i<=n;++i) { scanf("%s",s+1); for(int j=1;j<=n;++j) mp[i][j]=s[j]=='Y' ? true : false; } int l=0,r=n,mid,ans; while(l<=r) { mid=l+r>>1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } cout<<ans; }