网络流 Dinic 算法笔记
网络流 Dinic 算法笔记
步骤
- 建图,初始时令反向边权值为零,之后将该边每次用去的权值累计赋值给该反向边。
- 分层,每次只能找下一个层的点。
- 每次多向找增广路,并将跑满的边去掉,之后再去跑残量网络,直到榨干所有可用管道。
大致就这样,然后注意时时减脂优化。
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=200+5;
int iter[N];
int n,m,s,t;
const int MAXN=(1<<30);
struct edge{
int to,v,re;
};
vector<edge>g[N];
#define FOR(i,_l,_r) for(int i=_l;i<=_r;i++)
void build(int u,int v,int w){
g[u].push_back(edge{v,w,(int)g[v].size()});
g[v].push_back(edge{u,0,(int)g[u].size()-1});
}
int depth[N];
void bfs(){
memset(depth,-1,sizeof depth);
queue<int>q;
depth[s]=0;
q.push(s);
while(q.size()){
int u=q.front();q.pop();
for(auto &e:g[u]){
if(e.v>0&&depth[e.to]<0){
depth[e.to]=depth[u]+1;
q.push(e.to);
}
}
}
}
int dfs(int u,int f){
if(u==t||!f) return f;
int ans=0;
for(int &i=iter[u];i<(int)g[u].size();i++){//当前弧优化
edge &e=g[u][i];
if(e.v>0&&depth[e.to]==depth[u]+1){
int d=dfs(e.to,min(f,e.v));
if(d){
e.v-=d;
g[e.to][e.re].v+=d;
f-=d;ans+=d;
if(!f) break;
}
}
}
return ans;
}
int dinic(){
int ans=0;
while(1){
bfs();
if(depth[t]<0) return ans;
memset(iter,0,sizeof iter);
ans+=dfs(s,MAXN);
}
}
signed main(){
cin>>n>>m>>s>>t;
FOR(i,1,m){
int u,v,w;
cin>>u>>v>>w;
build(u,v,w);
}
cout<<dinic()<<endl;
return 0;
}
调试心得小结
- 注意存图时的反向边是建在哪个节点上的。
!f只能用来判断 \(f\) 是否为 \(0\) ,其于f<0并非等价,比如当 \(f\) 的值为 \(-1\) 时会出现无法预料的错误(调了好久)。- 是
#define int long long,不要吧int和long long错位,是用前一个关键字来代替后一个关键字,与typedef刚好相反。
完结撒花。
yingxilin
Qian·JX の joker
2024-12-28 于玉山一中

浙公网安备 33010602011771号