EK 複雜度O(V*E*E)
#define N 204
int c[N][N];//邊容量
int f[N][N];//邊實際流量
int pre[N];//記錄增廣路徑
int res[N];//殘餘網絡
queue<int> qq;
void init(){
while(!qq.empty())qq.pop();
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
}
int EK(int s,int t){
int i,j;
int ans=0;
while(1){
memset(res,0,sizeof(res));
res[s] = MAX;//源點的殘留網絡要置爲無限大!否則下面找增廣路出錯
pre[s] = -1;
qq.push(s);
//bfs找增廣路徑
while(!qq.empty()){
int x = qq.front();
qq.pop();
for(i=1;i<=t;i++){
if(!res[i] && f[x][i] < c[x][i]){
qq.push(i);
pre[i] = x;
res[i] = min(c[x][i] - f[x][i], res[x]);//這裏類似dp,如果有增廣路,那麼res[t]就是增廣路的最小權
}
}
}
if(res[t]==0)break;//找不到增廣路就退出
int k = t;
while(pre[k]!=-1){
f[pre[k]][k] += res[t];//正向邊加上新的流量
f[k][pre[k]] -= res[t];//反向邊要減去新的流量,反向邊的作用是給程序一個後悔的機會
k = pre[k];
}
ans += res[t];
}
return ans;
}
Dinic遞歸(推薦)
#define M 400
struct node {
int u, v, next, cap;
} edge[M*M];
int next[M], head[M], layer[M], Q[M * 2], mark[M];
int ecnt;
void init(){
ecnt= 0;
memset(head,-1,sizeof(head));
}
void add(int u, int v, int c) {
edge[ecnt].u = u;
edge[ecnt].v = v;
edge[ecnt].cap = c;
edge[ecnt].next = head[u];
head[u] = ecnt++;
edge[ecnt].u = v;
edge[ecnt].v = u;
edge[ecnt].cap = 0;
edge[ecnt].next = head[v];
head[v] = ecnt++;
}
bool BFS(int begin, int end) {
int i, l, h, k, y;
for (i = 0; i <= end; i++) layer[i] = -1;
layer[begin] = 0;
l = h = 0;
Q[l++] = begin;
while (h < l) {
k = Q[h++];
for (i = head[k]; i != -1; i = edge[i].next) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == -1) {
layer[y] = layer[k] + 1;
if (y == end)
return true;
Q[l++] = y;
}
}
}
return false;
}
int DFS(int x, int exp, int end) {
mark[x] = 1;
if (x == end)return exp;
int y, temp, i;
for (i = next[x]; i != -1; i = edge[i].next, next[x] = i) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == layer[x] + 1 && !mark[y]) {
if ((temp = (DFS(y, min(exp, edge[i].cap), end))) > 0) {
edge[i].cap -= temp;//流完後正向流表示剩餘流量
edge[i^1].cap += temp;//流完後反向流表示正向流的流量
return temp;
}
}
}
return 0;
}
int Dinic_flow(int begin, int end) {
int i, ans = 0, flow;
while (BFS(begin, end)) {
for (i = 0; i <= end; i++)next[i] = head[i];
while (true) {
for (i = 0; i <= end; i++) mark[i] = 0;
flow = DFS(begin, INT_MAX, end);
if (flow == 0)break;
ans += flow;
}
}
return ans;
}
Dinic非遞歸 複雜度O(V^2*E)
#define N 20100 #define sta que //靜態鄰接表 int level[N]; int p[N],p1[N]; int ecnt; int que[N]; int n,m; struct edge{ int v,next; int c; }e[900000]; void init(){ ecnt = 0; memset(p,-1,sizeof(p)); } void insert(int u,int v,int c,int w){ e[ecnt].v = v; e[ecnt].c = c; e[ecnt].next = p[u]; p[u] = ecnt++; e[ecnt].v = u; e[ecnt].c = w; e[ecnt].next = p[v]; p[v] = ecnt++; } int Dinic(int st,int ed){ int ans = 0; int i,u,v,c; int head,rear,top; while(1){//重建層次圖 memset(level,0,sizeof(level)); head = rear = 0; level[st]=1; que[rear++]=st; while(head<rear){ u = que[head++]; for(i=p[u];i!=-1;i=e[i].next){ v = e[i].v; c = e[i].c; if(c && level[v] == 0){ level[v] = level[u]+1; que[rear++]=v; } } } if(level[ed] == 0){//無增廣路 break; } memcpy(p1,p,sizeof(p1)); top = -1; while(1){ if(top<0){ for(i=p1[st];i!=-1;i=e[i].next){ v = e[i].v; c = e[i].c; if(c && p1[v] != -1 && level[v] == 2)break; } if(i>=0){ sta[++top] = i; p1[st] = e[i].next; } else break; } u = e[sta[top]].v; if(u == ed){//找到一條增廣路 //計算流的可改進量,並記錄離源點最遠的可能會組成下一條增廣路徑的邊 int dd = MAX,index = -1; for(i=0;i<=top;i++){ if(dd>e[sta[i]].c){ dd = e[sta[i]].c; index = i; } } ans += dd; //調整殘餘網絡 for(i=0;i<=top;i++){ //直接由上一殘餘網絡計算當前殘餘網絡 見導論P401 e[sta[i]].c -= dd; e[sta[i]^1].c += dd; } //回溯到路徑上某個可能繼續增廣的頂點,若該頂點也無法增廣,則回溯到前一個頂點(1) for(i=0;i<=top;i++){ if(e[sta[i]].c==0){ top = index-1; break; } } } else { for(i=p1[u];i!=-1;i = e[i].next){ v = e[i].v; c = e[i].c; if(c && p1[v]!=-1 && level[u]+1 == level[v])break; } if(i!=-1){ sta[++top] = i; p1[u] = e[i].next;//若沿着邊i找到了增廣路,則p1會被從新初始化;否則斷定從邊i出發無法到達匯點,以後搜索增廣路將不再考慮此邊。估可將其忽略 } else { p1[u] = -1; top--; } } } } return ans; }
SAP非遞歸 複雜度O(V*V*E)
#define N 440
#define M N*N
#define inf 1<<30
int head[N];
struct Edge {
int v,next,c;
}edge[M];
int ecnt;
void init(){
ecnt = 0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w) {
edge[ecnt].v=v;
edge[ecnt].c=w;
edge[ecnt].next=head[u];
head[u]=ecnt++;
edge[ecnt].v=u;
edge[ecnt].c=0;
edge[ecnt].next=head[v];
head[v]=ecnt++;
}
int sap(int s,int t,int nodenum){ //源,匯,匯點編號(非點數)
int pre[N],cur[N],dis[N],gap[N];
int flow=0,aug=inf;
int u;
bool flag;
int i,j;
for(i=0;i<=nodenum;i++){
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=nodenum;
u=pre[s]=s;
while(dis[s]<nodenum){
flag=0;
for(j=cur[u];j!=-1;j=edge[j].next){
int v=edge[j].v;
if(edge[j].c>0 && dis[u]==dis[v]+1){
flag=1;
cur[u] = j;
aug = min(aug,edge[j].c);
pre[v]=u;
u=v;
if(u==t){
flow+=aug;
while(u!=s){
u=pre[u];
edge[cur[u]].c -= aug; //邊的正流不斷減少
edge[cur[u]^1].c += aug; //反流增加
}
aug=inf;
}
break;
}
}
if(flag)continue;
if(--gap[dis[u]] == 0)break;
for(dis[u] = nodenum, j=head[u]; j!=-1; j=edge[j].next){
int v=edge[j].v;
if(edge[j].c>0 && dis[v]<dis[u]){
dis[u]=dis[v];
cur[u]=j;
}
}
dis[u]++;
gap[dis[u]]++;
u=pre[u];
}
return flow;
}
ISAP + GAP優化 複雜度O(V^2*E)
#define N 20010
#define M 500010
int n,m;//n爲點數 m爲邊數
int h[N];
int gap[N];
int p[N],ecnt;
int source,sink;
struct edge{
int v;
int next;//下一條邊的編號
int val;//邊權值
}e[M];
inline void init(){memset(p,-1,sizeof(p));ecnt=0;}
//有向
inline void add1(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=0;
e[ecnt].next=p[from];
p[from]=ecnt++;
}
//無向
inline void add2(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
}
inline int dfs(int pos,int cost){
if (pos==sink){
return cost;
}
int j,minh=n-1,lv=cost,d;
for (j=p[pos];j!=-1;j=e[j].next){
int v=e[j].v,val=e[j].val;
if(val>0){
if (h[v]+1==h[pos]){
if (lv<e[j].val) d=lv;
else d=e[j].val;
d=dfs(v,d);
e[j].val-=d;
e[j^1].val+=d;
lv-=d;
if (h[source]>=n) return cost-lv;
if (lv==0) break;
}
if (h[v]<minh) minh=h[v];
}
}
if (lv==cost){
--gap[h[pos]];
if (gap[h[pos]]==0) h[source]=n;
h[pos]=minh+1;
++gap[h[pos]];
}
return cost-lv;
}
int sap(int st,int ed){
source=st;
sink=ed;
int ans=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[st]=n;
while (h[st]<n){
ans+=dfs(st,INT_MAX);
}
return ans;
}