0.网络流解释:如果你还是不能理解,我们就换一种说法,假设s城有inf个人想去t城,但是从s到t要经过一些城市才能到达,(以上图为例)其中s到3城的火车票还剩10张,3到t的火车票还剩15张,其他路以此类推,问最终最多能有多少人能到达t城?(假设这个地区只有火车,没有汽车飞机,步行和骑自行车会累死就不考虑了,再假设所有人都买得起火车票。)
1.https://www.cnblogs.com/zsboy/archive/2013/01/27/2878810.html EK 算法 ,但是“反悔”那个图应该9 1 9 1 9 。
2. Dinic算法可以每次找出多条增广路,为什么要分层呢?分层图是有向无环图。
每bfs一次的结果在运行框中。
//在什么情况下用它?
//如何实现?
//最小费用最大流
//最大流的方法,不论走哪条路线,最终都会求出整个图的最大流
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#define INF 0x7fffffff
#define int long long
using namespace std;
int n,m,s,t,hd[205],cnt = 1, pre[205], f[205], ed[205];
struct Edge{
int to,nxt,w;
}edge[10005];
void add(int u, int v, int w){
cnt++;
edge[cnt].to = v;
edge[cnt].nxt = hd[u];
edge[cnt].w = w;
hd[u] = cnt;
}
int bfs(){
queue<int> q;
f[s] = INF;q.push(s);
memset(pre,-1,sizeof pre);
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = hd[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(edge[i].w > 0 && pre[v] == -1){
f[v] = min(f[u], edge[i].w);
pre[v] = u;
ed[v] = i;//一开始边没有写对
q.push(v);
if(v == t) return 1;
}
}
}
return 0;
}
int ek(){
int mxflow = 0;
while(bfs()){
mxflow += f[t];
for(int i = t; i != s; i = pre[i]){
edge[ed[i]].w -= f[t];
edge[ed[i]^1].w += f[t];
}
}
return mxflow;
}
signed main(){
scanf("%lld%lld%lld%lld",&n,&m,&s,&t); int u,v,w;
for(int i = 1; i <= m; i++){
scanf("%lld%lld%lld",&u,&v,&w);
add(u,v,w);
add(v,u,0);
}
printf("%lld\n",ek());
return 0;
}
dinic
#include<bits/stdc++.h>
#define inf 0x7fffffffffffffff
typedef long long ll;
using namespace std;
int cnt = 1, hd[205],n,m,s,t,x,y,z,dep[205],cur[205];
ll mxflow;
struct Edge{
int to,nxt,w;
}edge[10005];
void add(int u, int v, int w){
cnt++;
edge[cnt].to = v;
edge[cnt].nxt = hd[u];
edge[cnt].w = w;
hd[u] = cnt;
}
queue<int> q;
int bfs(){
memset(dep, 0, sizeof dep);
while(!q.empty()) q.pop();
q.push(s); dep[s] = 1; cur[s] = hd[s];
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = hd[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(edge[i].w && !dep[v]){
dep[v] = dep[u] + 1;
cur[v] = hd[v];
q.push(v);
if(v == t) return 1;
}
}
}
return 0;
}
ll dinic(int u, ll flow){//dinic函数表示这点以后的最大流量
if(u == t) return flow;
ll res = flow;
for(int i = cur[u]; i; i = edge[i].nxt){
cur[u] = i;
int v = edge[i].to;
if(res && dep[v] == dep[u] + 1 && edge[i].w){
int k = dinic(v, min(ll(edge[i].w), res));//res和edge[i].w的最小值,决定往后传的最小值
if(!k) dep[v] = 0;//我与终点(顺着残量网络)不连通
edge[i].w -= k;
edge[i^1].w += k;
res -= k;
}
}
return flow - res;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,0);
}
while(bfs()){
ll flow = 0;
while(flow = dinic(s, inf))
mxflow += flow;
}
printf("%lld\n",mxflow);
return 0;
}
上下界网络流:
https://www.cnblogs.com/verjun/archive/2004/01/13/13154188.html