BZOJ1305dance跳舞(最大流,裂点,二分答案)
Posted myx12345
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1305dance跳舞(最大流,裂点,二分答案)相关的知识,希望对你有一定的参考价值。
题意:一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。 有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。 给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?
n<=50,k<=30
思路:明显的最大流问题
将每个男,女都裂成两个点,一个表示喜欢,另一个表示不喜欢
二分答案
(S,num[i,1]) 流量为mid
(num[i,4],T) mid
(num[i,1],num[i,2]) (num[i,3],num[i,4]) k
对于互相喜欢的i,j:
(num[i,1],num[j,4]) 1
不喜欢:
(num[i,2],num[j,3]) 1
判maxflow是否=mid*n即可
1 var head,gap,dis:array[0..10000]of longint; 2 vet,next,len,fan:array[1..200000]of longint; 3 num:array[1..50,1..4]of longint; 4 a:array[1..50,1..50]of char; 5 n,m,i,l,r,mid,last,s,source,src,tot,k1,j:longint; 6 ch:string; 7 8 procedure add(a,b,c:longint); 9 begin 10 inc(tot); 11 next[tot]:=head[a]; 12 vet[tot]:=b; 13 len[tot]:=c; 14 head[a]:=tot; 15 inc(tot); 16 next[tot]:=head[b]; 17 vet[tot]:=a; 18 len[tot]:=0; 19 head[b]:=tot; 20 end; 21 22 function min(x,y:longint):longint; 23 begin 24 if x<y then exit(x); 25 exit(y); 26 end; 27 28 function dfs(u,aug:longint):longint; 29 var e,v,t,val,flow:longint; 30 begin 31 if u=src then exit(aug); 32 e:=head[u]; val:=s-1; flow:=0; 33 while e<>0 do 34 begin 35 v:=vet[e]; 36 if len[e]>0 then 37 begin 38 if dis[u]=dis[v]+1 then 39 begin 40 t:=dfs(v,min(len[e],aug-flow)); 41 len[e]:=len[e]-t; 42 len[fan[e]]:=len[fan[e]]+t; 43 flow:=flow+t; 44 if dis[source]>=s then exit(flow); 45 if aug=flow then break; 46 end; 47 val:=min(val,dis[v]); 48 end; 49 e:=next[e]; 50 end; 51 if flow=0 then 52 begin 53 dec(gap[dis[u]]); 54 if gap[dis[u]]=0 then dis[source]:=s; 55 dis[u]:=val+1; 56 inc(gap[dis[u]]); 57 end; 58 exit(flow); 59 end; 60 61 function maxflow:longint; 62 var ans:longint; 63 begin 64 fillchar(gap,sizeof(gap),0); 65 fillchar(dis,sizeof(dis),0); 66 gap[0]:=s; ans:=0; 67 while dis[source]<s do ans:=ans+dfs(source,maxlongint); 68 exit(ans); 69 end; 70 71 procedure build; 72 var i,j:longint; 73 begin 74 fillchar(head,sizeof(head),0); 75 tot:=0; 76 for i:=1 to n do 77 begin 78 add(num[i,1],num[i,2],k1); 79 add(num[i,3],num[i,4],k1); 80 end; 81 for i:=1 to n do 82 begin 83 add(source,num[i,1],mid); 84 add(num[i,4],src,mid); 85 end; 86 for i:=1 to n do 87 for j:=1 to n do 88 if a[i,j]=‘Y‘ then add(num[i,1],num[j,4],1) 89 else add(num[i,2],num[j,3],1); 90 end; 91 92 begin 93 assign(input,‘bzoj1305.in‘); reset(input); 94 assign(output,‘bzoj1305.out‘); rewrite(output); 95 readln(n,k1); 96 for i:=1 to n do 97 begin 98 readln(ch); 99 for j:=1 to n do a[i,j]:=ch[j]; 100 end; 101 for i:=1 to 200000 do 102 if i mod 2=1 then fan[i]:=i+1 103 else fan[i]:=i-1; 104 for i:=1 to n do 105 for j:=1 to 4 do 106 begin 107 inc(s); num[i,j]:=s; 108 end; 109 source:=s+1; src:=s+2; s:=s+2; 110 l:=0; r:=n; last:=0; 111 while l<=r do 112 begin 113 mid:=(l+r)>>1; 114 build; 115 if maxflow>=mid*n then begin last:=mid; l:=mid+1; end 116 else r:=mid-1; 117 end; 118 writeln(last); 119 close(input); 120 close(output); 121 end.
以上是关于BZOJ1305dance跳舞(最大流,裂点,二分答案)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)