• BZOJ1305: [CQOI2009]dance跳舞


    1305: [CQOI2009]dance跳舞

    Time Limit: 5 Sec  Memory Limit: 162 MB
    Submit: 1314  Solved: 574
    [Submit][Status]

    Description

    一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?

    Input

    第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。

    Output

    仅一个数,即舞曲数目的最大值。

    Sample Input

    3 0
    YYY
    YYY
    YYY

    Sample Output

    3

    HINT

    N<=50 K<=30

    Source

    题解:
    我是这样想的:
    1.因为有和不喜欢的人跳舞,还有和喜欢的人跳舞,所以应该把每个点拆成两个 num[i,1],num[i,2]
    2.如果男生i 喜欢 女生 j,那我们连边num[i,1]到num[j,1]否则我们连边 num[i,2]到num[j,2]
    3.因为每次都必须有n对,才能算一首曲子,所以我们从小到大枚举答案,当然不用重构图
       每次给每个人只加1的流量,如果某一次发现maxflow<n就退出出,输出 i-1
       至于选择不喜欢的人还是喜欢的人,由最大流决定,所以我们还得应增一个点num[i,3],由它向num[i,1]连容量为inf的边,num[i,2]连容量为k的边
       每次枚举答案的时候由 s向num[i,3](男生)连边,num[i,3](女生)向t连边
    4.也就是说num[i,3]是用来限制每一次的流量,必须使得一个男生只能跳一次,一个女生只能和一个男生跳
    5. 至于到了下一次的时候上一次新添的边是否应该回边无效化,我也不知道,无效和不无效都能A
    代码:
      1 const inf=maxlongint;maxn=5000;maxm=500000;
      2 type node=record
      3      from,go,next,v:longint;
      4      end;
      5 var  tot,i,j,n,m,maxflow,l,r,s,t,x,y,cnt:longint;
      6      h,head,q,cur:array[0..2*maxn] of longint;
      7      e:array[0..2*maxm] of node;
      8      num:array[0..2*maxn,1..3] of longint;
      9      ch:char;
     10      function min(x,y:longint):longint;
     11       begin
     12       if x<y then exit(x) else exit(y);
     13       end;
     14 procedure ins(x,y,z:longint);
     15  begin
     16  inc(tot);
     17  e[tot].from:=x;e[tot].go:=y;e[tot].v:=z;e[tot].next:=head[x];head[x]:=tot;
     18  end;
     19 procedure insert(x,y,z:longint);
     20  begin
     21  ins(x,y,z);ins(y,x,0);
     22  end;
     23 function bfs:boolean;
     24  var i,x,y:longint;
     25  begin
     26  fillchar(h,sizeof(h),0);
     27  l:=0;r:=1;q[1]:=s;h[s]:=1;
     28  while l<r do
     29   begin
     30   inc(l);
     31   x:=q[l];
     32   i:=head[x];
     33   while i<>0 do
     34    begin
     35    y:=e[i].go;
     36    if (e[i].v<>0) and (h[y]=0) then
     37     begin
     38      h[y]:=h[x]+1;
     39      inc(r);q[r]:=y;
     40     end;
     41    i:=e[i].next;
     42    end;
     43   end;
     44  exit (h[t]<>0);
     45  end;
     46 function dfs(x,f:longint):longint;
     47  var i,y,used,tmp:longint;
     48  begin
     49  if x=t then exit(f);
     50  used:=0;
     51  i:=cur[x];
     52  while i<>0 do
     53   begin
     54   y:=e[i].go;
     55   if (h[y]=h[x]+1) and (e[i].v<>0) then
     56    begin
     57    tmp:=dfs(y,min(e[i].v,f-used));
     58    dec(e[i].v,tmp);if e[i].v<>0 then cur[x]:=i;
     59    inc(e[i xor 1].v,tmp);
     60    inc(used,tmp);
     61    if used=f then exit(f);
     62    end;
     63   i:=e[i].next;
     64   end;
     65  if used=0 then h[x]:=-1;
     66  exit(used);
     67  end;
     68 procedure dinic;
     69  var i:longint;
     70  begin
     71  while bfs do
     72   begin
     73   for i:=s to t do cur[i]:=head[i];
     74   inc(maxflow,dfs(s,inf));
     75   end;
     76  end;
     77 procedure init;
     78  begin
     79  tot:=1;
     80  readln(n,m);
     81  for i:=1 to 2*n do
     82   begin
     83    inc(cnt);num[i,1]:=cnt;
     84    inc(cnt);num[i,2]:=cnt;
     85    inc(cnt);num[i,3]:=cnt;
     86    if i<=n then
     87     begin
     88     insert(num[i,3],num[i,1],inf);
     89     insert(num[i,3],num[i,2],m);
     90     end
     91    else
     92     begin
     93     insert(num[i,1],num[i,3],inf);
     94     insert(num[i,2],num[i,3],m);
     95     end;
     96   end;
     97  s:=0;t:=6*n+1;
     98  for i:=1 to n do
     99   begin
    100    for j:=1 to n do
    101     begin
    102     read(ch);
    103     if ch='Y' then insert(num[i,1],num[j+n,1],1)
    104     else insert(num[i,2],num[j+n,2],1);
    105     end;
    106    readln;
    107   end;
    108  end;
    109 procedure main;
    110  begin
    111  for i:=1 to n+1 do
    112    begin
    113    // for j:=1 to tot do if (e[j].go=t) or (e[j].from=t) then e[j].v:=0;
    114     for j:=1 to 2*n do if j<=n then insert(s,num[j,3],1) else insert(num[j,3],t,1);
    115     maxflow:=0;
    116     dinic;
    117     if maxflow<>n then break;
    118    end;
    119  writeln(i-1);
    120  end;
    121 begin
    122  assign(input,'input.txt');assign(output,'output.txt');
    123  reset(input);rewrite(output);
    124  init;
    125  main;
    126  close(input);close(output);
    127 end.   
    View Code
     
     
  • 相关阅读:
    剑指offer--面试题14--收获
    剑指offer--面试题14
    剑指offer--面试题13
    剑指offer--面试题12
    剑指offer--面试题11
    高质量代码
    剑指offer--面试题10--相关
    剑指offer--面试题10
    位运算及其操作
    负数在计算机中的表示方法
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3913882.html
Copyright © 2020-2023  润新知