博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
1305: [CQOI2009]dance跳舞 - BZOJ
阅读量:5334 次
发布时间:2019-06-15

本文共 3339 字,大约阅读时间需要 11 分钟。

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:=mid100         else r:=mid-1;101       end;102     write(l);103 end.
View Code

 

 

 

转载于:https://www.cnblogs.com/Randolph87/p/3659695.html

你可能感兴趣的文章
【BZOJ-2295】我爱你啊 暴力
查看>>
【BZOJ-1055】玩具取名 区间DP
查看>>
Oracle安装配置—64位Win7安装配置64位Oracle
查看>>
Bit Twiddling Hacks
查看>>
[USACO08MAR]土地征用Land Acquisition
查看>>
Windwos中的线程同步
查看>>
LeetCode : Reverse Vowels of a String
查看>>
时间戳与日期的相互转换
查看>>
jmeter(五)创建web测试计划
查看>>
python基本数据类型
查看>>
1305: [CQOI2009]dance跳舞 - BZOJ
查看>>
关于TDD的思考
查看>>
Cocos2d-x学习之windows 7 android环境搭建
查看>>
将html代码中的大写标签转换成小写标签
查看>>
jmeter多线程组间的参数传递
查看>>
零散笔记
查看>>
第1章2节《MonkeyRunner源码剖析》概述:边界(原创)
查看>>
ubuntu16下面 redis 无法链接到客户端问题
查看>>
android下实现4分屏播放4路高清h264格式的rtsp流
查看>>
[计算机网络] vsftpd的安装与使用
查看>>