bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)

1305: [CQOI2009]dance跳舞

题目:传送门 

题解:

   一眼网络流基础建模...然后就GG了

   二分答案+拆点建边+最大流判断:
   把男女生拆为男1,男2,女1,女2

   1、男1和男2还有女1和女2之间连边,流量为约束条件k

   2、st连男1,女2连ed,流量为二分的mid

   3、如果男生i喜欢女生j,就将男1与女2相连(不在约束条件内)

   4、如果不喜欢,就将男2与女1相连(在约束条件内)

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 char ss[55][55];
  8 struct node
  9 {
 10     int x,y,c,next,other;
 11 }a[2110000];int len,last[1110000];
 12 int st,ed,head,tail,n,k;
 13 void ins(int x,int y,int c)
 14 {
 15     int k1,k2;
 16     k1=++len;
 17     a[len].x=x;a[len].y=y;a[len].c=c;
 18     a[len].next=last[x];last[x]=len;
 19     
 20     k2=++len;
 21     a[len].x=y;a[len].y=x;a[len].c=0;
 22     a[len].next=last[y];last[y]=len;
 23     
 24     a[k1].other=k2;
 25     a[k2].other=k1;
 26 }
 27 int h[1110000],list[1110000];
 28 bool bt_h()
 29 {
 30     memset(h,0,sizeof(h));h[st]=1;
 31     head=1;tail=2;list[1]=st;
 32     while(head!=tail)
 33     {
 34         int x=list[head];
 35         for(int k=last[x];k;k=a[k].next)
 36         {
 37             int y=a[k].y;
 38             if(h[y]==0 && a[k].c)
 39             {
 40                 h[y]=h[x]+1;
 41                 list[tail++]=y;
 42             }
 43         }
 44         head++;
 45     }
 46     if(h[ed])return true;
 47     return false;
 48 }
 49 int find_flow(int x,int flow)
 50 {
 51     if(x==ed)return flow;
 52     int t,s=0;
 53     for(int k=last[x];k;k=a[k].next)    
 54     {
 55         int y=a[k].y;
 56         if(h[y]==(h[x]+1) && a[k].c && s<flow)
 57         {
 58             s+=t=find_flow(y,min(a[k].c,flow-s));
 59             a[k].c-=t;a[a[k].other].c+=t;
 60         }
 61     }
 62     if(s==0)h[x]=0;
 63     return s;
 64 }
 65 int mid,l,r;
 66 int s1[55],s2[55];
 67 void build(int cc)
 68 {
 69     len=0;memset(last,0,sizeof(last));
 70     st=4*n+1;ed=st+1;
 71     for(int i=1;i<=n;i++)ins(st,i,cc);
 72     for(int i=1;i<=n;i++)ins(i+n*3,ed,cc);
 73     for(int i=1;i<=n;i++)ins(i,i+2*n,k);
 74     for(int i=1;i<=n;i++)ins(i+n,i+n*3,k);
 75     /*for(int i=1;i<=n;i++)
 76     {
 77         ins(st,i,cc);
 78         ins(i,i+n*2,s1[i]+k);//男1-->男2 
 79     }
 80     for(int j=1;j<=n;j++)
 81     {
 82         ins(j+n*3,ed,cc);
 83         ins(j+n,j+n*3,s2[j]+k);//女1-->女2 
 84     }*/
 85     for(int i=1;i<=n;i++)//男2-->女1 
 86         for(int j=1;j<=n;j++)
 87         {
 88             if(ss[i][j]=='Y')ins(i,j+n*3,1);
 89             else ins(i+n*2,j+n,1);
 90         }
 91 }
 92 bool check(int cnt)
 93 {
 94     build(cnt);
 95     int ans=0;
 96     while(bt_h())
 97         ans+=find_flow(st,999999999);
 98     if(ans==n*cnt)return true;
 99     return false;
100 }
101 int main()
102 {
103     scanf("%d%d",&n,&k);
104     for(int i=1;i<=n;i++)scanf("%s",ss[i]+1);
105     l=1;r=n;int sum=0;
106     while(l<=r)
107     {
108         mid=(l+r)/2;
109         if(check(mid))
110         {
111             l=mid+1;
112             sum=mid;
113         }
114         else r=mid-1;
115     }
116     printf("%d\n",sum);
117     return 0;
118 }
posted @ 2018-03-04 16:42  CHerish_OI  阅读(254)  评论(0编辑  收藏  举报