今天拿网络流写二分图最大匹配,心血来潮写了一下 HLPP(其实写 Dinic 就可以了,但是我还是要写 HLPP),结果发现 HLPP 写二分图最大匹配会 RE,求助这一现象的原因。
另外,HLPP 板子能过网络最大流模板题,数组大小足够,只把 HLPP 的板子换成 Dinic 的板子就可以 AC。
下面是 HLPP 的代码:
#include <stdio.h>
#include <algorithm>
#include <numeric>
#include <queue>
#include <stack>
#define qaq inline
using ll=long long;
const int inf=0x3FFFFFFF;
const int sz=1009;
const int esz=3e5+19;
int n,m,s,t;
int lgsz,rgsz;
int head[sz],hpp=1;
struct edge{
int nxt,to,val;
}graph[esz];
qaq void addEdge(int from,int to,int val){
graph[++hpp]=edge{head[from],to,val};
head[from]=hpp;
}
int ht[sz],exFlow[sz],gap[sz],evLevel=0;
std::stack<int> bucket[sz];
int push(int u){
bool init=(u==s);
for(int p=head[u];p!=0;p=graph[p].nxt){
const auto &v=graph[p].to,&w=graph[p].val;
if(w==0||(!init&&ht[u]!=ht[v]+1)) continue;
int k=init?w:std::min(w,exFlow[u]);
if(v!=s&&v!=t&&exFlow[v]==0)
bucket[ht[v]].push(v),evLevel=std::max(evLevel,ht[v]);
exFlow[u]-=k,exFlow[v]+=k,graph[p].val-=k,graph[p^1].val+=k;
if(exFlow[u]==0) return 0;
}
return 1;
}
void relebel(int u){
ht[u]=inf;
for(int p=head[u];p!=0;p=graph[p].nxt){
if(graph[p].val!=0) ht[u]=std::min(ht[u],ht[graph[p].to]);
}
if(++ht[u]<n){
bucket[ht[u]].push(u);
evLevel=std::max(evLevel,ht[u]);
++gap[ht[u]];
}
}
bool BFS(){
std::fill(ht,ht+n+10,inf);
std::queue<int> q;
q.push(t),ht[t]=0;
while(!q.empty()){
int u=q.front();
q.pop();
for(int p=head[u];p!=0;p=graph[p].nxt){
const auto &v=graph[p].to;
if(graph[p^1].val!=0&&ht[v]>ht[u]+1)
ht[v]=ht[u]+1,q.push(v);
}
}
return ht[s]!=inf;
}
int select(){
while(bucket[evLevel].empty()&&evLevel>-1) --evLevel;
return evLevel==-1?0:bucket[evLevel].top();
}
int HLPP(){
if(!BFS()) return 0;
std::fill(gap,gap+n+10,0);
for(int cx=1;cx<=n;++cx){
if(ht[cx]!=inf)
gap[ht[cx]]++;
}
ht[s]=n,push(s);
int u;
while((u=select())!=0){
bucket[evLevel].pop();
if(push(u)!=0){
if(gap[ht[u]]==0){
for(int cx=1;cx<=n;++cx){
if(cx!=s&&cx!=t&&ht[cx]>ht[u]&&ht[cx]<n+1)
ht[cx]=n+1;
}
}
relebel(u);
}
}
return exFlow[t];
}
int main(){
scanf("%d%d%d",&lgsz,&rgsz,&m);
n=lgsz+rgsz+2;
for(int cx=0,u,v;cx<m;++cx){
scanf("%d%d",&u,&v);
addEdge(u,v+lgsz,1);
addEdge(v+lgsz,u,0);
}
s=n-1,t=n;
for(int cx=1;cx<=lgsz;++cx){
addEdge(s,cx,1);
addEdge(cx,s,0);
}
for(int cx=1;cx<=rgsz;++cx){
addEdge(cx+lgsz,t,1);
addEdge(t,cx+lgsz,0);
}
int ans=HLPP();
printf("%d\n",ans);
return 0;
}