D20 网络流 最大流 EK 算法

视频链接:https://www.bilibili.com/video/BV1o94y1271C/

// Luogu P3376 【模板】网络最大流
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
#define N 10010
#define M 200010
using namespace std;

int n,m,S,T;
struct edge{LL v,c,ne;}e[M];
int h[N],idx=1;//从2,3开始配对
LL mf[N],pre[N];

void add(int a,int b,int c){
  e[++idx]={b,c,h[a]};
  h[a]=idx;
}
bool bfs(){//找增广路
  memset(mf,0,sizeof mf);
  queue<int> q;
  q.push(S); mf[S]=1e9;
  while(q.size()){
    int u=q.front(); q.pop();
    for(int i=h[u];i;i=e[i].ne){
      LL v=e[i].v;
      if(mf[v]==0 && e[i].c){
        mf[v]=min(mf[u],e[i].c);
        pre[v]=i;//存前驱边
        q.push(v);
        if(v==T)return true;
      }
    }
  }
  return false;
}
LL EK(){//累加可行流
  LL flow=0;
  while(bfs()){
    int v=T;
    while(v!=S){//更新残留网
      int i=pre[v];
      e[i].c-=mf[T];
      e[i^1].c+=mf[T];
      v=e[i^1].v;
    }
    flow+=mf[T];
  }
  return flow;
}
int main(){
  int a,b,c;
  scanf("%d%d%d%d",&n,&m,&S,&T);
  while(m--){
    scanf("%d%d%d",&a,&b,&c);
    add(a,b,c); 
    add(b,a,0);//反向边
  }
  printf("%lld\n",EK());
  return 0;
}

 

// Luogu P3376 【模板】网络最大流
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define LL long long
#define N 10010
#define M 200010
using namespace std;

int n,m,S,T;
struct edge{LL u,v,c;};
vector<edge> e;
vector<int> h[N];
LL mf[N],pre[N];

void add(int a,int b,int c){
  e.push_back({a,b,c});
  h[a].push_back(e.size()-1);
}
bool bfs(){//找增广路
  memset(mf,0,sizeof mf);
  queue<int> q;
  q.push(S); mf[S]=1e9;
  while(q.size()){
    int u=q.front(); q.pop();
    for(int i=0;i<h[u].size();i++){
      int j=h[u][i];
      LL v=e[j].v;
      if(mf[v]==0 && e[j].c){
        mf[v]=min(mf[u],e[j].c);
        pre[v]=j;//存前驱边
        q.push(v);
        if(v==T)return true;
      }
    }
  }
  return false;
}
LL EK(){//累加可行流
  LL flow=0;
  while(bfs()){
    int v=T;
    while(v!=S){//更新残留网
      int i=pre[v];
      e[i].c-=mf[T];
      e[i^1].c+=mf[T];
      v=e[i^1].v;
    }
    flow+=mf[T];
  }
  return flow;
}
int main(){
  int a,b,c;
  scanf("%d%d%d%d",&n,&m,&S,&T);
  while(m--){
    scanf("%d%d%d",&a,&b,&c);
    add(a,b,c); 
    add(b,a,0);//反向边
  }
  printf("%lld\n",EK());
  return 0;
}

 

posted @ 2022-05-28 13:34  董晓  阅读(844)  评论(2编辑  收藏  举报