zoukankan      html  css  js  c++  java
  • 1305: [CQOI2009]dance跳舞

    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

    二分答案+最大流判定

    把男和女每个点都拆成两个节点,一个处理喜欢的,一个处理不喜欢的,男的为i和i',女的为j和j'

    假设我们二分的答案为p

    那么从s向所有的i连容量为p的边,从所有的j向t连容量为p的边

    喜欢的男女对应的i向j连容量为1的边,不喜欢的男女对应的i向j连容量为1的边

    所有的男的i向i'连容量为k的边,所有女的j'向j连容量为k的边

    如果可行,那么最大流为p*n

    上述算法的正确性基于以下定理:
    若二分图中,X部中点度数全为t,Y部中点度数全为t,那么该图定存在t个完全不同的完备匹配。
    用归纳法易证。

    t=1时一定是对的,当t>1时,直接去掉一个匹配,就变成了t-1的问题了

    现在我们就是要证明的是,t>0时一定存在一个匹配,当t=1时,有唯一的匹配,当t>1时,显然至少有一个匹配(我不知道怎么严格的证明......有的话留言给我吧,谢谢)

    网上还看见有贪心的做法,我觉得不对,我也写了一个贪心的做法,WA了,估计是因为贪心不对,所以BZOJ加强了数据吧

    我觉得贪心不对是因为这个

    我们一开始给了无限大的流量(喜欢的为无限大,不喜欢的为k),然后取最小值,但是这样流量参差不齐,我们在减少那些大的流量时,可能会把这些小的流量变得更小(我自己瞎想的,勿喷)

      1 const
      2     maxn=55;
      3     inf=10000;
      4 var
      5     map:array[0..maxn*4,0..maxn*4]of longint;
      6     a:array[0..maxn,0..maxn]of char;
      7     n,k,s,t,l,r,mid:longint;
      8  
      9 procedure init;
     10 var
     11     i,j:longint;
     12 begin
     13     readln(n,k);
     14     s:=0;
     15     t:=4*n+1;
     16     for i:=1 to n do
     17       begin
     18         for j:=1 to n do
     19           read(a[i,j]);
     20         readln;
     21       end;
     22 end;
     23  
     24 var
     25     his,dis,vh,pre:array[0..maxn*4]of longint;
     26     min,aug,flow:longint;
     27     flag:boolean;
     28  
     29 function sap:boolean;
     30 var
     31     i,j:longint;
     32 begin
     33         fillchar(map,sizeof(map),0);
     34     fillchar(dis,sizeof(dis),0);
     35     fillchar(vh,sizeof(vh),0);
     36     flow:=0;
     37     for i:=1 to n do
     38       for j:=1 to n do
     39         if a[i,j]='Y' then map[2*i,2*j+2*n]:=1
     40         else map[2*i-1,2*j+2*n-1]:=1;
     41     for i:=1 to n do
     42       begin
     43         map[s,2*i]:=mid;
     44         map[2*i+2*n,t]:=mid;
     45         map[2*i,2*i-1]:=k;
     46         map[2*i+2*n-1,2*i+2*n]:=k;
     47       end;
     48     vh[0]:=t+1;
     49     i:=s;
     50     aug:=inf;
     51     while dis[i]<=t do
     52       begin
     53         his[i]:=aug;
     54         flag:=false;
     55         for j:=s to t do
     56           if (map[i,j]>0) and (dis[i]=dis[j]+1) then
     57           begin
     58             pre[j]:=i;
     59             flag:=true;
     60             if aug>map[i,j] then aug:=map[i,j];
     61             i:=j;
     62             if i=t then
     63             begin
     64               inc(flow,aug);
     65               while i<>s do
     66                 begin
     67                   inc(map[i,pre[i]],aug);
     68                   dec(map[pre[i],i],aug);
     69                   i:=pre[i];
     70                 end;
     71               aug:=inf;
     72             end;
     73             break;
     74           end;
     75         if flag then continue;
     76         min:=t;
     77         for j:=s to t do
     78           if (map[i,j]>0) and (min>dis[j]) then min:=dis[j];
     79         dec(vh[dis[i]]);
     80         if vh[dis[i]]=0 then break;
     81         dis[i]:=min+1;
     82         inc(vh[dis[i]]);
     83         if i<>s then
     84         begin
     85           i:=pre[i];
     86           aug:=his[i];
     87         end;
     88       end;
     89     exit(flow=mid*n);
     90 end;
     91  
     92 begin
     93     init;
     94     l:=0;
     95     r:=n;
     96     while l<>r do
     97       begin
     98         mid:=(l+r+1)>>1;
     99         if sap then l:=mid
    100         else r:=mid-1;
    101       end;
    102     write(l);
    103 end.
    View Code
  • 相关阅读:
    Flutter 步骤进度组件
    程序员到底要不要学习框架、库和工具
    Flutter 吐血整理组件继承关系图
    超过百万的StackOverflow Flutter 问题
    Flutter 实现网易云音乐字幕
    Flutter 实现虎牙/斗鱼 弹幕效果
    Flutter AbsorbPointer 与 IgnorePointer的区别
    《Flutter 小技巧》一行禁用App,一行置灰App,致敬
    Python 任务自动化工具:nox 的配置与 API
    Flask 作者 Armin Ronacher:我不觉得有异步压力
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3659695.html
Copyright © 2011-2022 走看看