HLPP 为什么会 RE 二分图最大匹配呢?
查看原帖
HLPP 为什么会 RE 二分图最大匹配呢?
496840
SAMSHAWCRAFT楼主2022/2/12 22:53

今天拿网络流写二分图最大匹配,心血来潮写了一下 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;
}
2022/2/12 22:53
加载中...