让我们继续来练网络流;

很明显是一个最大流的问题;

二分枚举最多次数m,然后最大流判定;

具体就是男生女生都拆成两个点i1,i2,之间连一条流量为k的边(男生i1-->i2,女生i2-->i1);

i2连不喜欢的人,i1连喜欢的人

最后,男生i1连源点流量为m,女生i1连汇点流量为m

最后判断最大流是否等于n*m即可

但做着做着,我发现好像好像二分+最大流不是很优,因为进行了很多重复操作

但我也没管,先A了再说;

后来看status发现很多人代码很短,用时0ms(我的最大流180ms)

肯定有更简单的方法:

贪心!……其实是错的……

  1 code(using maxflow):
  2 type node=record
  3        next,point,flow:longint;
  4      end;
  5 
  6 var edge:array[0..200010] of node;
  7     a:array[0..60,0..60] of boolean;
  8     cur,pre,p,numh,h:array[0..400] of longint;
  9     j,m,n,k,i,len,t,ans,l,r:longint;
 10     c:string;
 11 
 12 function min(a,b:longint):longint;
 13   begin
 14     if a>b then exit(b) else exit(a);
 15   end;
 16 
 17 procedure add(x,y,f:longint);
 18   begin
 19     inc(len);
 20     edge[len].flow:=f;
 21     edge[len].point:=y;
 22     edge[len].next:=p[x];
 23     p[x]:=len;
 24   end;
 25 
 26 function sap(m:longint):boolean;
 27   var s,u,tmp,i,j,q:longint;
 28   begin
 29     len:=-1;
 30     fillchar(p,sizeof(p),255);
 31     for i:=1 to n do
 32     begin
 33       add(0,i,m);
 34       add(i,0,m);
 35       add(i+2*n,t,m);
 36       add(t,i+2*n,0);
 37       add(i,i+n,k);
 38       add(i+n,i,0);
 39       add(i+3*n,i+2*n,k);
 40       add(i+2*n,i+3*n,0);
 41     end;
 42     for i:=1 to n do
 43       for j:=1 to n do
 44         if a[i,j] then
 45         begin
 46           add(i,j+2*n,1);
 47           add(j+2*n,i,0);
 48         end
 49         else begin
 50           add(i+n,j+3*n,1);
 51           add(j+3*n,i+n,0);
 52         end;
 53     fillchar(numh,sizeof(numh),0);
 54     fillchar(h,sizeof(h),0);
 55     numh[0]:=t+1;
 56     u:=0;
 57     s:=0;
 58     while h[0]<t+1 do
 59     begin
 60       if u=t then
 61       begin
 62         i:=0;
 63         while i<>t do
 64         begin
 65           j:=cur[i];
 66           dec(edge[j].flow);
 67           inc(edge[j xor 1].flow);
 68           i:=edge[j].point;
 69         end;
 70         u:=0;
 71         inc(s);
 72         if s=n*m then exit(true);
 73       end;
 74       q:=-1;
 75       i:=p[u];
 76       while i<>-1 do
 77       begin
 78         j:=edge[i].point;
 79         if (edge[i].flow>0) and (h[u]=h[j]+1) then
 80         begin
 81           q:=i;
 82           break;
 83         end;
 84         i:=edge[i].next;
 85       end;
 86       if q<>-1 then
 87       begin
 88         cur[u]:=q;
 89         pre[j]:=u;
 90         u:=j;
 91       end
 92       else begin
 93         dec(numh[h[u]]);
 94         if numh[h[u]]=0 then exit(false);
 95         tmp:=t+1;
 96         i:=p[u];
 97         while i<>-1 do
 98         begin
 99           j:=edge[i].point;
100           if edge[i].flow>0 then tmp:=min(tmp,h[j]);
101           i:=edge[i].next;
102         end;
103         h[u]:=tmp+1;
104         inc(numh[h[u]]);
105         if u<>0 then u:=pre[u];
106       end;
107     end;
108     exit(false);
109   end;
110 
111 begin
112   readln(n,k);
113   for i:=1 to n do
114   begin
115     readln(c);
116     for j:=1 to n do
117     begin
118       if c[j]='Y' then a[i,j]:=true
119       else a[i,j]:=false;
120     end;
121   end;
122   t:=n*4+1;
123   l:=1;
124   r:=n;
125   ans:=0;
126   while l<=r do
127   begin
128     m:=(l+r) shr 1;
129     if sap(m) then
130     begin
131       ans:=m;
132       l:=m+1;
133     end
134     else r:=m-1;
135   end;
136   writeln(ans);
137 end.
View Code

 

posted on 2014-05-04 21:45  acphile  阅读(186)  评论(0编辑  收藏  举报