bzoj1305: [CQOI2009]dance跳舞
这题一眼过去网络流,关键是怎么流的问题。。
然后回忆起了好久没用过的二分答案+网络流。
解法很神奇,主要是构图问题,直接看代码应该看得懂吧(懒得写23333
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct node { int x,y,c,next,other; }a[2100000];int len,last[110000]; void ins(int x,int y,int c) { if(c==0)return ; int k1,k2; len++;k1=len; a[len].x=x;a[len].y=y;a[len].c=c; a[len].next=last[x];last[x]=len; //printf("%d %d %d\n",x,y,c); len++;k2=len; a[len].x=y;a[len].y=x;a[len].c=0; a[len].next=last[y];last[y]=len; a[k1].other=k2; a[k2].other=k1; } int st,ed; int h[110000],list[110000]; bool bt_h() { memset(h,0,sizeof(h));h[st]=1; int head=1,tail=2;list[1]=st; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(h[y]==0&&a[k].c>0) { h[y]=h[x]+1; list[tail]=y; tail++; } } head++; } if(h[ed]==0)return false; return true; } int findflow(int x,int f) { if(x==ed)return f; int s=0; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(h[y]==h[x]+1&&a[k].c>0&&s<f) { int t=findflow(y,min(a[k].c,f-s)); s+=t;a[k].c-=t;a[a[k].other].c+=t; } } if(s==0)h[x]=0; return s; } //-------findflow---------- int n,k; int Yb[110],Yg[110];char mp[110][110]; bool check(int mid) { //st->boy(1~n)->bl(n+1~n*2)、bu(n*2+1~n*3)-> //gl(n*3+1~n*4)、gu(n*4+1~n*5)->girl(n*5+1,n*6)->ed st=n*6+1,ed=n*6+2; len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) ins(st,i,mid), ins(i+n*5,ed,mid); for(int i=1;i<=n;i++) { int B=i,bl=i+n,bu=i+2*n; ins(B,bl,Yb[i]); ins(B,bu,k); int G=i+n*5,gl=i+n*3,gu=i+n*4; ins(gl,G,Yg[i]); ins(gu,G,k); } for(int B=1;B<=n;B++) { int bl=B+n,bu=B+2*n; for(int G=1;G<=n;G++) { int gl=G+n*3,gu=G+n*4; if(mp[B][G]=='Y')ins(bl,gl,1); else ins(bu,gu,1); } } //-----composition------- int ans=0; while(bt_h()==true) { ans+=findflow(st,999999999); } if(ans==n*mid)return true; return false; } int main() { //freopen("dance.in","r",stdin); //freopen("dance.out","w",stdout); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%s",mp[i]+1); memset(Yb,0,sizeof(Yb)); memset(Yg,0,sizeof(Yg)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(mp[i][j]=='Y') Yb[i]++, Yg[j]++; int l=1,r=n,ans=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)==true) { l=mid+1; ans=mid; } else r=mid-1; } printf("%d\n",ans); return 0; }
pain and happy in the cruel world.