# 最大流

## EK算法

$BFS$每次只寻找一条增广路，找到以后增广，然后重复之前步骤直到找不到增广路结束。

inline void EK(){
int u;
for(;;){
memset(a,0,sizeof(a));
while(!q.empty()) q.pop();
q.push(S);
a[S] = INF;
while(!q.empty()){
u = q.front(); q.pop();
for(int i = head[u]; i != -1; i = nxt[i]){
if(!a[to[i]] && c[i]-f[i]>0){
pre[to[i]] = i;//这一步我们记录边的编号，以便更新流量。我们只需要在一次BFS中找一条增广路，而每一次发现一条边可行便更新其对应终点对应的边，因为u已经可行所以这样记录一定没有问题。结束后从T点向前找一定能找到对应增广路
a[to[i]] = min(a[u],c[i]-f[i]);
q.push(to[i]);
}
}
if(a[T]) break;
}
if(!a[T]) break;
for(int x = T; x != S; x = from[pre[x]]){
f[pre[x]] += a[T];
f[pre[x]^1] -= a[T];
}
ans += a[T];
}
}


## Dinic算法

### $Code$

/*DennyQi 2019*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 10010;
const int M = 100010;
const int P = 998244353;
const int INF = 0x3f3f3f3f;
int x(0),w(1); char c = getchar();
while(c^'-' && (c<'0' || c>'9')) c = getchar();
if(c=='-') w = -1, c = getchar();
while(c>='0' && c<='9') x = (x<<3)+(x<<1)+c-'0', c = getchar();
return x*w;
}
int n,m,S,T,ans,x,y,z,cur[N],h,t,q[N],lv[N];
inline int corres(int i){
return (i&1) ? i+1 : i-1;
}
inline void add(int u, int v, int C, int F){
to[++cnte] = v;
c[cnte] = C;
f[cnte] = F;
}
inline bool BFS(){
memset(lv,0,sizeof(lv));
h = t = 0;
int u;
lv[S] = 1;
q[++t] = S;
while(h < t){
u = q[++h];
for(int i = head[u]; i != -1; i = nxt[i]){
if(lv[to[i]] || c[i]-f[i]==0) continue;
lv[to[i]] = lv[u]+1;
q[++t] = to[i];
}
}
return lv[T];
}
//DFS(u,a)返回在当前状态下，从$u$出发，该点初始容量为$a$的最大可行流。
int DFS(int u, int a){
if(u == T || !a) return a;
int res=0, F;
for(int& i = cur[u]; i != -1; i = nxt[i]){
if(lv[to[i]]==lv[u]+1 && c[i]-f[i]>0){
F = DFS(to[i],min(a,c[i]-f[i]));
a -= F;
res += F;
f[i] += F, f[i^1] -= F;
if(!a) break;
}
}
return res;
}
inline void Dinic(){
while(BFS()){
for(int i = 1; i <= n; ++i) cur[i] = head[i];
ans += DFS(S,INF);
}
}
int main(){
// freopen("file.in","r",stdin);
for(int i = 1; i <= m; ++i){
}
Dinic();
printf("%d\n",ans);
return 0;
}


# 最小费用最大流

/*DennyQi 2019*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 5010;
const int M = 50010;
const int P = 998244353;
const int INF = 0x3f3f3f3f;
int x(0),w(1); char c = getchar();
while(c^'-' && (c<'0' || c>'9')) c = getchar();
if(c=='-') w = -1, c = getchar();
while(c>='0' && c<='9') x = (x<<3)+(x<<1)+c-'0', c = getchar();
return x*w;
}
int n,m,S,T,x,y,z,p,ans1,ans2,pre[N],inq[N],d[N];
queue <int> q;
inline void add(int u, int v, int C, int F, int V){
to[++cnte] = v, from[cnte] = u;
c[cnte] = C, f[cnte] = F, val[cnte] = V;
}
inline bool spfa(){
memset(d,0x3f,sizeof(d));
memset(inq,0,sizeof(inq));
memset(pre,-1,sizeof(pre));
q.push(S);
d[S] = 0;
while(!q.empty()){
int u = q.front(); q.pop();
inq[u] = 0;
for(int i = head[u]; i != -1; i = nxt[i]){
if(c[i]-f[i] > 0 && d[u]+val[i] < d[to[i]]){
d[to[i]] = d[u]+val[i];
pre[to[i]] = i;
if(!inq[to[i]]){
inq[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return pre[T]!=-1;
}
inline void EK(){
while(spfa()){
int a = INF;
for(int x = T; x != S; x = from[pre[x]]){
a = min(a,c[pre[x]]-f[pre[x]]);
}
ans1 += a;
for(int x = T; x != S; x = from[pre[x]]){
f[pre[x]] += a;
f[pre[x]^1] -= a;
ans2 += a*val[pre[x]];
}
}
}
int main(){
// freopen("file.in","r",stdin);
for(int i = 1; i <= m; ++i){
}
EK();
printf("%d %d\n",ans1,ans2);
return 0;
}


# 最大权闭合子图

posted @ 2019-08-03 08:11  DennyQi  阅读(175)  评论(0编辑  收藏  举报