bzoj1532

就题目而言,这道题是裸的二分+最大流

但是这样是TLE的,我们考虑优化

1. 我们可以先贪心,这样二分的上界就可以

2. 最大流我们可以不急着跑增广路,我们可以先贪心一个流然后再跑增广路

但是我们发现上述优化还是不足以通过这题

我们考虑是不是sap不适合处理这张图(这是二分图)呢?确实是这样的

考虑到sap判断h[s]<t+1,但实际上二分图的增广路不可能太长,我们把这个条件改成h[s]<100

duang的一下,就飞快的跑过了(460ms)

而事实证明dinic似乎没有这种问题,因为根据证明,dinic跑二分图和HK算法是一样的复杂度

  1 type node=record
  2        po,next,flow:longint;
  3      end;
  4
  5 var e:array[0..200010] of node;
  6     w,pre,numh,p,h,cur,x,y:array[0..20010] of longint;
  7     ans,t,i,n,m,l,r,mid,len,need:longint;
  8
  9 procedure add(x,y,f:longint);
 10   begin
 11     inc(len);
 12     e[len].po:=y;
 13     e[len].flow:=f;
 14     e[len].next:=p[x];
 15     p[x]:=len;
 16   end;
 17
 18 procedure build(x,y,f1,f2:longint);
 19   begin
 20     add(x,y,f1);
 21     add(y,x,f2);
 22   end;
 23
 24 function sap:longint;
 25   var i,j,q,u,tmp:longint;
 26   begin
 27     fillchar(numh,sizeof(numh),0);
 28     fillchar(h,sizeof(h),0);
 29     for i:=0 to t do
 30       cur[i]:=p[i];
 31     u:=0; sap:=0;
 32     while (h[0]<t+1) and (h[0]<100) do  //重要优化
 33     begin
 34       i:=cur[u];
 35       while i<>-1 do
 36       begin
 37         j:=e[i].po;
 38         if (e[i].flow>0) and (h[u]=h[j]+1) then
 39         begin
 40           cur[u]:=i;
 41           pre[j]:=u;
 42           u:=j;
 43           if u=t then
 44           begin
 45             inc(sap);
 46             if sap=need then exit;
 47             while u<>0 do
 48             begin
 49               u:=pre[u];
 50               j:=cur[u];
 51               dec(e[j].flow);
 52               inc(e[j xor 1].flow);
 53             end;
 54           end;
 55           break;
 56         end;
 57         i:=e[i].next;
 58       end;
 59       if i=-1 then
 60       begin
 61         dec(numh[h[u]]);
 62         if numh[h[u]]=0 then exit;
 63         i:=p[u];
 64         tmp:=t;
 65         q:=-1;
 66         while i<>-1 do
 67         begin
 68           j:=e[i].po;
 69           if e[i].flow>0 then
 70             if tmp>h[j] then
 71             begin
 72               q:=i;
 73               tmp:=h[j];
 74             end;
 75           i:=e[i].next;
 76         end;
 77         h[u]:=tmp+1;
 78         inc(numh[h[u]]);
 79         cur[u]:=q;
 80         if u<>0 then u:=pre[u];
 81       end;
 82     end;
 83   end;
 84
 85 procedure swap(var a,b:longint);
 86   var c:longint;
 87   begin
 88     c:=a;
 89     a:=b;
 90     b:=c;
 91   end;
 92
 93 function check(h:longint):boolean;
 94   var i:longint;
 95   begin
 96     len:=-1;
 97     fillchar(p,sizeof(p),255);
 98     need:=0;
 99     for i:=1 to n do
100       w[i]:=h;
101     for i:=1 to m do  //贪心初始流
102     begin
103       if w[x[i]]<w[y[i]] then swap(x[i],y[i]);
104       if w[x[i]]=0 then
105       begin
106         build(i,x[i]+m,1,0);
107         build(0,i,1,0);
108         inc(need);
109       end
110       else begin
111         dec(w[x[i]]);
112         build(0,i,0,1);
113         build(i,x[i]+m,0,1);
114       end;
115       build(i,y[i]+m,1,0);
116     end;
117     if need=0 then exit(true);
118     for i:=1 to n do
119       build(i+m,t,w[i],h-w[i]);
120     if sap=need then exit(true) else exit(false);
121   end;
122
123 begin
124   readln(n,m);
125   for i:=1 to m do
126   begin
127     readln(x[i],y[i]);
128     if w[x[i]]<w[y[i]] then inc(w[x[i]]) else inc(w[y[i]]);
129   end;
130   for i:=1 to n do
131     if w[i]>r then r:=w[i];  //贪心上界
132   t:=n+m+1;
133   l:=0;
134   while l<=r do
135   begin
136     mid:=(l+r) shr 1;
137     if check(mid) then
138     begin
139       ans:=mid;
140       r:=mid-1;
141     end
142     else l:=mid+1;
143   end;
144   writeln(ans);
145 end.

时间: 2024-10-20 22:20:01

bzoj1532的相关文章

[bzoj1532] [POI2005]Kos-Dicing

二分答案,比赛与双方选手连边跑最大匹配..看匹配数是否等于比赛数. dinic大法好++ 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=10233,inf=1002333333; 6 struct zs{ 7 int too,pre,flow; 8 }e[maxn<<3];int tot,last[maxn

【分块答案】【最小割】bzoj1532 [POI2005]Kos-Dicing

引用zky的题解:http://blog.csdn.net/iamzky/article/details/39667859 每条S-T路径代表一次比赛的结果.最小割会尽量让一个人赢得最多. 因为二分总是写挂,所以写了分块答案,比暴力枚举好像快不了多少. #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using names

bzoj网络流

近期看了一些bzoj的网络流,深感智商不够.不过对于网络流又有了进一步的理解. 还是mark一下吧. 献上几篇论文:1)<最小割模型在信息学竞赛中的应用> 2)<浅析一类最小割问题> 1.bzoj1066(最大流) 题意:戳这里 思路:很明显拆点最大流模型,然后对于每个点每个高度流量限为1,那么根据最大流即为可以出去的蜥蜴的数量. 2.bzoj1077(费用流) 戳这里 3.bzoj1391(最小割) 题意:戳这里 思路:有点像最大权闭合图..可以利用最小割的性质建图: <S

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

[转载]hzwer的bzoj题单

counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ1202 BZOJ1051 BZOJ1001 BZOJ1588 BZOJ1208 BZOJ1491 BZOJ1084 BZOJ1295 BZOJ3109 BZOJ1085 BZOJ1041 BZOJ1087 BZOJ3038 BZOJ1821 BZOJ1076 BZOJ2321 BZOJ1934 BZOJ