# Edmonds-Karp算法简介

Edmonds-Karp算法使用BFS不断寻找增广路，直到没有增广路存在，则为最大流

# Edmonds-Karp算法模板

struct edge{   //储存边
int from,to,flow,cap;
edge(int u,int v,int f,int c):from(u),to(v),flow(f),cap(c){}
}

vector<edge>edges;
vector<int>g[maxn];
int a[manx],p[maxn];

edges.push_back(edge(from,to,0,c));
edges.push_back(edge(to,from,0,0));   //加一条容量为0的反向边
m=edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}

int Edmonds-Karp(int s,int t){
int flow;
while(1){
memset(a,0,sizeof(a));
queue<int>q;
q.push(s);
a[s]=INF;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0;i<g[x].size();i++){
edge& e=edges[g[x][i]];
if(!a[e.to]&&e.cap>e.flow){
p[e.to]=g[x][i];
a[e.to]=min(a[x],e.cap-e.flow);
q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u=t;u!=s;u=edges[p[u]].from){
edges[p[u].flow+=a[t];
edges[p[u]^1].flow-=a[t];
}
flow+=a[t];
}
return flow;
}


# Dinic算法简介

Dinic算法通过BFS构造层次图，然后用DFS用阻塞流来增广

# Dinic算法模板

const int INF=1<<30;

struct edge{   //储存边
int from,to,flow,cap;
edge(int u,int v,int f,int c):from(u),to(v),flow(f),cap(c){}
}

vector<edge>edges;
vector<int>g[maxn];
int vis[manx],d[maxn]; //d[maxn]储存结点的层级
int cur[maxn] //记录每个结点考虑到的弧

edges.push_back(edge(from,to,0,c));
edges.push_back(edge(to,from,0,0));   //加一条容量为0的反向边
m=edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}

int bfs(){
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0;i<g[x].size();i++){
edge& e=edge[g[x][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=1;
d[e.to]=d[x]+1;
q.push(e.to);
}
}
}
return vis[t];
}

int dfs(int x,int a){
if(x==t||a==0) return a; //余量为0或者到达汇点时为边界
int flow=0,f;
for(int &i=cur[x];i<g[x].size();i++){
cur[x]=i;
edge& e=edges[g[x][i]];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
e.flow+=f;
edges[g[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
}

int Dinic(int s,int t){
int flow=0;
while(bfs()){
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}


## 习题

1.UVA - 10330
https://cn.vjudge.net/problem/UVA-10330

## 最小割问题

ac代码

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<string.h>
#include<stdlib.h>
using namespace std;
typedef long long ll;

const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=6e5;
int n,s,t;
int tot=0,to[maxn],nxt[maxn];
ll flow[maxn],cap[maxn];

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int judge(int a,int b){
int c=a*a+b*b;
int x=sqrt(c);
if(gcd(a,b)==1&&x*x==c) return 1;
return 0;
}

}

int bfs(){
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
if(!vis[to[i]]&&cap[i]>flow[i]){
vis[to[i]]=1;
d[to[i]]=d[x]+1;
q.push(to[i]);
}
}
}
return vis[t];
}

ll dfs(int x,ll a){
if(x==t||a==0) return a;
ll flo=0,f;
for(int &i=cur[x];~i;i=nxt[i]){
cur[x]=i;
if(d[x]+1==d[to[i]]&&(f=dfs(to[i],min(a,cap[i]-flow[i])))>0){
flow[i]+=f;
flow[i^1]-=f;
flo+=f;
a-=f;
if(a==0) break;
}
}
return flo;
}

ll dinic(){
int flo=0;
while(bfs()){
for(int i=0;i<=n+1;i++){
}
flo+=dfs(s,INF);
}
return flo;
}

int main(){
long long sum=0;
scanf("%d",&n);
s=0;t=n+1;
for(int i=1;i<=n;i++) {scanf("%d",a+i);sum=sum+a[i];}
for(int i=1;i<=n;i++){
if(a[i]&1){
for(int j=1;j<=n;j++){
if(a[j]&1) continue;
}
}
else{
for(int j=1;j<=n;j++){
if(a[i]&1==0) continue;
}
}
}
printf("%lld",sum-dinic());
return 0;
}



## 平面图跑最大流边数过大

http://blog.sina.com.cn/s/blog_60707c0f01011fnn.html

ac代码

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<queue>
typedef long long ll;
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=300000;
const int maxm=4005*1005;
int to[maxm],nxt[maxm],dis[maxm];
int n,s,t,tot=0;

}

struct node{		//用来结合优先队列使用
int d,u;
bool operator < (const node &rhs) const {
return d>rhs.d;
}
};

void dij(){
priority_queue<node> q;
for(int i=0;i<=t;i++) d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
q.push((node){0,s});
while(!q.empty()){
node x=q.top();q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=1;
if(d[to[i]]>d[u]+dis[i]){  	//松弛操作
d[to[i]]=d[u]+dis[i];
q.push((node){d[to[i]],to[i]});
}
}
}
}

void build(){
int c;
tot=0;
scanf("%d",&n);
s=0,t=n*n+1;
for(int i=0;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&c);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<=n;j++){
scanf("%d",&c);
}
}
for(int i=0;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&c);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<=n;j++){
scanf("%d",&c);
}
}
}

int main(){
build();
dij();
int flow=d[t];
printf("%d",flow);
}



08-16 55
12-20 732

06-23 2698
07-29 30
04-29 160
01-21 380
03-11 8万+
03-07 3022
07-16 4878