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; }