P4722 [Template] Maximum flow enhanced version / pre-flow advance

topic

topic

Ideas

Pre-flow advances the board.
Dinic, EK, and FF are all the same idea, namely cancellation, this algorithm is no exception, but the idea of ​​this algorithm is to introduce the concept of height like ISAP, in the process for each node to fill up the flow, each point If there is an excess flow , as long as there is only s in the network and the excess flow of t is not 0, it is a set of solutions.
code:

#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#include<list>
#include<map>
#include<queue>
#include<deque>
#define inf 0x3f3f3f3f
using namespace std;
int x,y,w;
struct f{
    
    
 int to,net,w;
} a[2000016];
int head[10001],gap[10001],h[10001],cel[10001];
bool vis[10001];
int n,m,s,t,tot;
struct cmp{
    
    
 bool operator ()(int x,int y)const
 {
    
    
  return h[x]<h[y];
 }
};
priority_queue<int,vector<int>,cmp > u;
queue<int> p;
void add(int x,int y,int w)
{
    
    
 a[tot].to=y;
 a[tot].w=w;
 a[tot].net=head[x];
 head[x]=tot;
 tot++;
 return;
}
bool bfs()
{
    
    
 memset(h+1,inf,sizeof(int)*n);
 h[t]=0;
 p.push(t);
 while (p.size())
 {
    
    
  int o=p.front();
  p.pop();
  for (int i=head[o];i!=-1;i=a[i].net)
  {
    
    
   if (a[i^1].w!=0&&h[a[i].to]>h[o]+1)
   {
    
    
    h[a[i].to]=h[o]+1;
    p.push(a[i].to);
   }
  }
 }
 return h[s]!=inf;
}
void push(int x)
{
    
    
 for (int i=head[x];i!=-1;i=a[i].net)
 {
    
    
  if (a[i].w&&h[x]==h[a[i].to]+1)
  {
    
    
   int temp=min(cel[x],a[i].w);
   a[i].w-=temp;
   a[i^1].w+=temp;
   cel[x]-=temp;
   cel[a[i].to]+=temp;
   if (a[i].to!=s&&a[i].to!=t&&vis[a[i].to]==0)
   {
    
    
    vis[a[i].to]=1;
    u.push(a[i].to);
   }
  }
  if (cel[x]==0) break;
 }
 return;
}
void relabel(int x)
{
    
    
 h[x]=inf;
 for (int i=head[x];i;i=a[i].net)
 {
    
    
  if (a[i].w!=0&&h[a[i].to]+1<h[x]) h[x]=h[a[i].to]+1;
 }
 return;
}
int hlpp()
{
    
    
 if (!bfs()) return 0;
 h[s]=n;
 memset(gap,0,sizeof(int)*(n<<1));
 for (int i=1;i<=n;i++) if (h[i]!=inf) gap[h[i]]++;
 for (int i=head[s];i!=-1;i=a[i].net)
 {
    
    
  if (a[i].w)
  {
    
    
   int temp=a[i].w;
   a[i].w-=temp;
   a[i^1].w+=temp;
   cel[s]-=temp;
   cel[a[i].to]+=temp;
   if (a[i].to!=s&&a[i].to!=t&&vis[a[i].to]==0)
   {
    
    
    vis[a[i].to]=1;
    u.push(a[i].to);
   }
  }
 }
 while (u.size())
 {
    
    
  int o=u.top();
  u.pop();
  vis[o]=0;
  push(o);
  if (cel[o])
  {
    
    
   gap[h[o]]--;
   if (!gap[h[o]])
   {
    
    
    for (int i=1;i<=n;i++)
    {
    
    
     if (i!=s&&i!=t&&h[i]>h[o]&&h[i]<n+1) h[i]=n+1;
    }
   }
   relabel(o);
   gap[h[o]]++;
   u.push(o);
   vis[o]=1;
  }
 }
 return cel[t];
}
signed main()
{
    
    
 scanf("%d%d%d%d",&n,&m,&s,&t);
    memset(head,-1,sizeof(head));
 for (int i=1;i<=m;i++)
 {
    
    
  long long w;
  scanf("%d%d%lld",&x,&y,&w);
  add(x,y,w);
  add(y,x,0);
 }
 long long uu=hlpp();
 printf("%lld",uu);
 return 0;
 }

Guess you like

Origin blog.csdn.net/weixin_49843717/article/details/114436398