网络流-最大流EK算法
源点S,汇点T
通过bfs找到增广路,并逆序构建残留网
累加可行流即为答案
链式前向星存图
注意边的编号从2开始,这是为了让编号^1时,是我们构建的退流管道边(即2的退流管道为3,4的退流管道为5...)
时间复杂度O(n*m^2)
int S,T;
struct edge{
int v,w,ne;
}e[maxn];
int idx=1;
int mf[maxn],pre[maxn];
//mf数组用来存节点v到源点S之间能通过的最大流量
int h[maxn];
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){
int v=e[i].v;
if(mf[v]==0&&e[i].w){
mf[v]=min(mf[u],e[i].w);
pre[v]=i;//记录每一个节点的前驱边,以便接下来的逆序
q.push(v);
if(v==T)return true;
}
}
}
return false;
}
int EK(){
int flow=0;
while(bfs()){
int v=T;
while(v!=S){
int i=pre[v];
e[i].w-=mf[T];
e[i^1].w+=mf[T];//退流管道
v=e[i^1].v;//(2->3)->4
}
flow+=mf[T];
}
return flow;
}
void solve(){
int n,m;cin>>n>>m;
cin>>S>>T;
rep(i,1,m){
int u,v,w;cin>>u>>v>>w;
add(u,v,w);
add(v,u,0);//构建退流管道
}
cout<<EK()<<endl;
}

浙公网安备 33010602011771号