网络流学习
入门
Tank_long讲的知识点(概念)很有价值
这哥们讲的也不错
谢谢cwen提供的题目和知识要点
嗯,我的代码还是很不错的
题目:luogu模板网络最大流
EK算法
//EK算法:模板来自yyb
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#define rg register
#define il inline
#define lst long long
#define ldb long double
#define N 10050
#define M 100050
using namespace std;
const int Inf=1e9;
il int read()
{
rg int s=0,m=0;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')m=1;ch=getchar();}
while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
}
int n,m,S,T,ans;
int hd[N],cnt=1;
int flow[N],pre[M];
queue<int> Q;
struct EDGE{int u,v,nxt,w,c,fb;}ljl[M<<1];
//流量,容量,反边编号
il void add(rg int p,rg int q,rg int o)
{
ljl[cnt]=(EDGE){p,q,hd[p],0,o,cnt+1},hd[p]=cnt++;//正向连边
ljl[cnt]=(EDGE){q,p,hd[q],0,0,cnt-1},hd[q]=cnt++;//连反边
}
int main()
{
freopen("s.in","r",stdin);
n=read(),m=read(),S=read(),T=read();
for(rg int i=1;i<=m;++i)
{
rg int p=read(),q=read(),o=read();
add(p,q,o);
}
while(233)//疯狂增广路
{
for(rg int i=1;i<=n;++i)flow[i]=0;
while(!Q.empty())Q.pop();
Q.push(S),pre[S]=0,flow[S]=Inf;//从源点开始增广
while(!Q.empty())
{
rg int now=Q.front();Q.pop();
for(rg int i=hd[now];i;i=ljl[i].nxt)
{
rg int qw=ljl[i].v;
if(!flow[qw]&&ljl[i].c>ljl[i].w)
{
flow[qw]=min(flow[now],ljl[i].c-ljl[i].w);//更新flow,路上的最小值
pre[qw]=i;//储存此点的增广由来
Q.push(qw);
}
}
if(flow[T])break;//增广完了就没必要继续
}
if(!flow[T])break;//不能增广就退出
for(rg int now=T;now!=S;now=ljl[pre[now]].u)
{
ljl[pre[now]].w+=flow[T];//正边流量增多
ljl[ljl[pre[now]].fb].w-=flow[T];//方便后悔,反边流量减少(感性理解一下……)
}
ans+=flow[T];//统计答案
}
printf("%d
",ans);
return 0;
}
Dinic算法
//Dinic算法:模板来自yyb
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#define rg register
#define il inline
#define lst long long
#define ldb long double
#define N 10050
#define M 100050
using namespace std;
const int Inf=1e9;
il int read()
{
rg int s=0,m=0;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')m=1;ch=getchar();}
while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
}
int n,m,S,T;
int hd[N],cnt=1;
int dep[N];
queue<int> Q;
struct EDGE{int to,nxt,c,fb;}ljl[M<<1];
il void add(rg int p,rg int q,rg int o)
{
ljl[cnt]=(EDGE){q,hd[p],o,cnt+1},hd[p]=cnt++;//存边
ljl[cnt]=(EDGE){p,hd[q],0,cnt-1},hd[q]=cnt++;//反边
}
il bool BFS()
//bfs找增广路,记录一个深度dep[]用于分层,有利于找到之后dfs
{
for(rg int i=1;i<=n;++i)dep[i]=0;
while(!Q.empty())Q.pop();
Q.push(S),dep[S]=1;//从S开始增广
while(!Q.empty())
{
rg int now=Q.front();Q.pop();
for(rg int i=hd[now];i;i=ljl[i].nxt)
{
rg int qw=ljl[i].to;
if(ljl[i].c&&!dep[qw])//还有容量&&没增广到
{
dep[qw]=dep[now]+1;//分层增广
Q.push(qw);
}
}
}
return dep[T];
}
int dfs(rg int now,rg int aim,rg int flow)
{
if(now==aim||(!flow))return flow;//到达终点||没有流量了 就不用增广了
rg int res=0;
for(rg int i=hd[now];i;i=ljl[i].nxt)
{
rg int qw=ljl[i].to;
if(ljl[i].c&&dep[qw]==dep[now]+1)//有流量&&深度刚好 符合条件去增广
{
rg int kk=dfs(qw,aim,min(flow,ljl[i].c));
res+=kk,flow-=kk;//局部最大流增加,可用流量减少
ljl[i].c-=kk,ljl[ljl[i].fb].c+=kk;//正边减少容量,反边增加容量……
}
}
return res;
}
il int Dinic()
{
rg int ans=0;
while(BFS())//可以增广就一直增广
ans+=dfs(S,T,Inf);//统计答案……
return ans;
}
int main()
{
n=read(),m=read(),S=read(),T=read();
for(rg int i=1;i<=m;++i)
{
rg int p=read(),q=read(),o=read();
add(p,q,o);
}
printf("%d
",Dinic());
return 0;
}