bzoj 1532 二分答案+最大流判断
2017-03-05 17:08
288 查看
题意:n个人,m场比赛,求赢得最多的人最少赢几场
妥妥的二分答案,然后建图判一下最大流是否等于比赛场数
建图:S -> 每个人(编号为i)边权为mid (表示每个人最多赢mid场)
每个人(编号为i) -> 参加的第j场比赛(编号为n+j)边权为1
每场比赛(编号为n+j) -> T 边权为1 (表示每场比赛最多有一个人赢)
type
rec=record
a,b:longint;
end;
var
n,m,x,ans,y,l :longint;
ll,rr,mid,ss,st :longint;
i :longint;
pre,other,len :array[0..100010] of longint;
game :array[0..10010] of rec;
last,dis,que :array[0..20010] of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure connect(x,y,z:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
len[l]:=z;
end;
function bfs:boolean;
var
i,h,tl,cur,p,q:longint;
begin
for i:=1 to st do dis[i]:=0;
h:=0; tl:=1; que[1]:=ss; dis[ss]:=1;
while (h<>tl) do
begin
h:=h mod 20005+1;
cur:=que[h];
q:=last[cur];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=0) and (len[q]>0) then
begin
dis[p]:=dis[cur]+1;
tl:=tl mod 20005+1;
que[tl]:=p;
if p=st then exit(true);
end;
q:=pre[q];
end;
end;
exit(false);
end;
function dinic(x,flow:longint):longint;
var
rest,tt,p,q:longint;
begin
if x=st then exit(flow);
rest:=flow;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=dis[x]+1) and (len[q]>0) and (rest>0) then
begin
tt:=dinic(p,min(len[q],rest));
dec(len[q],tt);
inc(len[q xor 1],tt);
dec(rest,tt);
if rest=0 then exit(flow);
end;
q:=pre[q];
end;
if rest=flow then dis[x]:=0;
exit(flow-rest);
end;
function check(x:longint):boolean;
var
i:longint;
tt:longint;
begin
fillchar(last,sizeof(last),0); l:=1; tt:=0;
for i:=1 to m do
begin
connect(game[i].a,n+i,1);
connect(n+i,game[i].a,0);
connect(game[i].b,n+i,1);
connect(n+i,game[i].b,0);
end;
for i:=n+1 to n+m do
begin
connect(i,st,1);
connect(st,i,0);
end;
for i:=1 to n do
begin
connect(ss,i,x);
connect(i,ss,0);
end;
while bfs do inc(tt,dinic(ss,maxlongint div 10));
if tt=m then exit(true) else exit(false);
end;
begin
read(n,m);
for i:=1 to m do read(game[i].a,game[i].b);
ss:=n+m+1; st:=ss+1;
ll:=1; rr:=m; ans:=maxlongint;
while (ll<=rr) do
begin
mid:=(ll+rr)>>1;
if check(mid) then
begin
if mid<ans then ans:=mid; rr:=mid-1;
end else ll:=mid+1;
end;
writeln(ans);
end.
——by Eirlys
![](https://img-blog.csdn.net/20170305170824345)
妥妥的二分答案,然后建图判一下最大流是否等于比赛场数
建图:S -> 每个人(编号为i)边权为mid (表示每个人最多赢mid场)
每个人(编号为i) -> 参加的第j场比赛(编号为n+j)边权为1
每场比赛(编号为n+j) -> T 边权为1 (表示每场比赛最多有一个人赢)
type
rec=record
a,b:longint;
end;
var
n,m,x,ans,y,l :longint;
ll,rr,mid,ss,st :longint;
i :longint;
pre,other,len :array[0..100010] of longint;
game :array[0..10010] of rec;
last,dis,que :array[0..20010] of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure connect(x,y,z:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
len[l]:=z;
end;
function bfs:boolean;
var
i,h,tl,cur,p,q:longint;
begin
for i:=1 to st do dis[i]:=0;
h:=0; tl:=1; que[1]:=ss; dis[ss]:=1;
while (h<>tl) do
begin
h:=h mod 20005+1;
cur:=que[h];
q:=last[cur];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=0) and (len[q]>0) then
begin
dis[p]:=dis[cur]+1;
tl:=tl mod 20005+1;
que[tl]:=p;
if p=st then exit(true);
end;
q:=pre[q];
end;
end;
exit(false);
end;
function dinic(x,flow:longint):longint;
var
rest,tt,p,q:longint;
begin
if x=st then exit(flow);
rest:=flow;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=dis[x]+1) and (len[q]>0) and (rest>0) then
begin
tt:=dinic(p,min(len[q],rest));
dec(len[q],tt);
inc(len[q xor 1],tt);
dec(rest,tt);
if rest=0 then exit(flow);
end;
q:=pre[q];
end;
if rest=flow then dis[x]:=0;
exit(flow-rest);
end;
function check(x:longint):boolean;
var
i:longint;
tt:longint;
begin
fillchar(last,sizeof(last),0); l:=1; tt:=0;
for i:=1 to m do
begin
connect(game[i].a,n+i,1);
connect(n+i,game[i].a,0);
connect(game[i].b,n+i,1);
connect(n+i,game[i].b,0);
end;
for i:=n+1 to n+m do
begin
connect(i,st,1);
connect(st,i,0);
end;
for i:=1 to n do
begin
connect(ss,i,x);
connect(i,ss,0);
end;
while bfs do inc(tt,dinic(ss,maxlongint div 10));
if tt=m then exit(true) else exit(false);
end;
begin
read(n,m);
for i:=1 to m do read(game[i].a,game[i].b);
ss:=n+m+1; st:=ss+1;
ll:=1; rr:=m; ans:=maxlongint;
while (ll<=rr) do
begin
mid:=(ll+rr)>>1;
if check(mid) then
begin
if mid<ans then ans:=mid; rr:=mid-1;
end else ll:=mid+1;
end;
writeln(ans);
end.
——by Eirlys
相关文章推荐
- BZOJ 1532 [POI2005]Kos-Dicing(二分+最大流判断)
- 【枚举】【二分答案】【分块答案】【BFS】【最大流】【Dinic】bzoj1189 [HNOI2007]紧急疏散evacuate
- BZOJ 3993 Sdoi2015 星际战争 二分答案+最大流
- bzoj1532 [POI2005]Kos-Dicing 最大流+二分
- 【bzoj1532】[POI2005]Kos-Dicing 二分+网络流最大流
- bzoj 3993: [SDOI2015]星际战争 二分答案+最大流
- 【BZOJ1189】【HNOI2007】紧急疏散evacuate 二分答案+最大流check
- BZOJ 1189 HNOI 2007 紧急疏散 evacuate 二分答案 最大流
- 【BZOJ1305】dance跳舞(最大流,裂点,二分答案)
- 【bzoj1738】[Usaco2005 mar]Ombrophobic Bovines 发抖的牛 二分答案+最大流
- bzoj 3035 二分答案+二分图最大匹配
- 【二分答案】【最大流】bzoj3993 [Sdoi2015]星际战争
- BZOJ 1570: [JSOI2008]Blue Mary的旅行( 二分答案 + 最大流 )
- 【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞
- bzoj 1532: [POI2005]Kos-Dicing (二分+最大流)
- BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流
- 【二分答案】【最大流】bzoj3130 [Sdoi2013]费用流
- BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
- BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
- bzoj 3993 星际战争 - 二分答案 - 最大流