网络流(自行理解的Dinic)
自行理解的Dinic 注释即讲解
#include<bits/stdc++.h> const int maxn=100008; using namespace std; int read() { char ch=getchar();int f=1,w=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();} return f*w; } //读入优化 struct sj{ int next; int to; int w; //w是剩余的流量 }a[maxn*2]; int head[maxn],size=1; //注意size 要赋值为1 否则会死循环 int m,n; int s,t; int cent[maxn]; //层数 int ans; void add(int x,int y,int z) { a[++size].to=y; a[size].next=head[x]; head[x]=size; a[size].w=z; } //加边 bool bfs() { memset(cent,-1,sizeof(cent)); //cent 层数先清零 queue <int> q; q.push(s); cent[s]=0; //起点进栈 while(q.empty()!=1) { int ks=q.front(); q.pop(); for(int i=head[ks];i;i=a[i].next) { int ts=a[i].to; if(cent[ts]==-1&&a[i].w>0) { q.push(ts); cent[ts]=cent[ks]+1; //层数加1 } } } if(cent[t]<0) //如果已经找不到增广路 return 0; return 1; } int dfs(int x,int low) //dfs搜索 参数:当前的点,当前最小的流量 { if(x==t)return low; //如果已经搜到终点了 就直接返回 int flow=0,r; //避免重复流 每次都新定义一个统计的流量 每层都各自求和 for(int i=head[x];i;i=a[i].next) { int st=a[i].to; if((a[i].w>0)&&(cent[st]==cent[x]+1)) { r=dfs(st,min(a[i].w,low-flow)); //递归在这里 if(r>0) { a[i].w-=r; //当前增广路走过的边 残量减掉这么多 a[i^1].w+=r; //反向边则加上这么多 flow+=r; //流量加上r 这次找已经流了这么多 } } } return flow; //递归返回时 则返回已经流完的流量 } int main() //主函数 { n=read();m=read(); s=read();t=read(); for(int i=1;i<=m;i++) { int x,y,z; x=read(); y=read(); z=read(); add(x,y,z); add(y,x,0); } //建立反向边 while(bfs()) { int row=dfs(s,0x3f3f3f); //row代表这次搜索找到的流量总和 ans+=row; cout<<row<<endl; } //还能找到增广路 cout<<ans; return 0; }