EK求最大流。
#include <queue>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 205
#define M 405
#define INF 0x7fffffff
#define min(a,b) a < b ? a : b
#define CLR(a,v) memset(a,v,sizeof(a))
struct Vertex
{
int head;
}V[N];
struct Edge
{
int v,c,f,next;
}E[M];
int pre[N],flow[N];
int top,s,t;
void Init()
{
top = 0;
CLR(V,-1);
}
void Add_edge(int u,int v,int c)
{
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].next = V[u].head;
V[u].head = top++;
}
bool Ed_Karp()
{
CLR(flow,0);
queue<int> Q;
Q.push(s);
flow[s] = INF;
while(!Q.empty())
{
int u = Q.front();
for(int i=V[u].head;i!=-1;i=E[i].next)
{
int v = E[i].v;
if(!flow[v] && E[i].c > E[i].f)
{
pre[v] = i;
flow[v] = min(flow[u],E[i].c-E[i].f); //flow[v] represents the min flow in the way from "s" to "v".
if(v == t)
return true;
Q.push(v);
}
}
Q.pop();
}
return false;
}
int Ford_Fulkerson()
{
int i,MaxFlow = 0;
while(Ed_Karp())
{
for(int v=t;v!=s;v=E[i^1].v)
{
i = pre[v];
E[i].f += flow[t];
E[i^1].f -= flow[t]; //cool
}
MaxFlow += flow[t];
}
return MaxFlow;
}
SAP求最大流。
#include <queue>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 205
#define M 405
#define INF 0x7fffffff
#define min(a,b) a < b ? a : b
#define CLR(a,v) memset(a,v,sizeof(a))
struct Vertex
{
int head;
}V[N];
struct Edge
{
int v,c,f,next;
}E[M];
int d[N],pre[N],cur[N],gap[N];
int top,s,t,n;
void Init()
{
top = 0;
CLR(V,-1);
}
void Add_edge(int u,int v,int c)
{
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].next = V[u].head;
V[u].head = top++;
}
void set_d()
{
queue<int> Q;
CLR(d,-1);
CLR(gap,0);
d[t] = 0;
Q.push(t);
while(!Q.empty())
{
int v = Q.front();
Q.pop();
++gap[ d[v] ];
for(int i=V[v].head;i!=-1;i=E[i].next)
{
int u = E[i].v;
if(d[u] == -1)
{
d[u] = d[v]+1;
Q.push(u);
}
}
}
}
int Sap()
{
set_d(); //You can replace it with "CLR(d,0)" if you feel it trouble
int MaxFlow = 0, u = s;
int flow = INF;
memcpy(cur,V,sizeof(V)); //current arc
while(d[s] < n)
{
int &i = cur[u]; //reference
for(;i!=-1;i=E[i].next)
{
int v = E[i].v;
if(E[i].c > E[i].f && d[u] == d[v]+1) //admissible arc
{
u = v;
pre[v] = i;
flow = min(flow,E[i].c-E[i].f);
if(u == t)
{
while(u != s)
{
int j = pre[u];
E[j].f += flow;
E[j^1].f -= flow;
u = E[j^1].v;
}
MaxFlow += flow;
flow = INF;
}
break;
}
}
if(i == -1) //there's no admissible arc.
{
if(--gap[ d[u] ] == 0)
break;
int dmin = n-1;
cur[u] = V[u].head;
for(int j=V[u].head;j!=-1;j=E[j].next)
if(E[j].c > E[j].f) //not full arc
dmin = min(dmin,d[ E[j].v ]);
d[u] = dmin+1;
++gap[ d[u] ];
if(u != s)
u = E[ pre[u]^1 ].v;
}
}
return MaxFlow;
}
最小费用最大流。(最小费用路算法)
需要注意的地方:加反向边时,费用为真实费用的负值。
#include <queue>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 105
#define M 5205
#define INF 0x3fffffff
#define min(a,b) a < b ? a : b
#define CLR(a,v) memset(a,v,sizeof(a))
struct Vertex
{
int head;
}V[N];
struct Edge
{
int v,c,f,cost,next;
}E[M];
int pre[N],dis[N];
int top,s,t;
bool in[N];
void Init()
{
top = 0;
CLR(V,-1);
}
void Add_edge(int u,int v,int c,int cost)
{
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].cost = cost;
E[top].next = V[u].head;
V[u].head = top++;
}
bool Spfa()
{
CLR(dis,63);
CLR(in,false);
queue<int> Q;
Q.push(s);
dis[s] = 0;
in[s] = true;
while(!Q.empty())
{
int u = Q.front();
for(int i=V[u].head;i!=-1;i=E[i].next)
{
int v = E[i].v;
if(dis[u]+E[i].cost < dis[v] && E[i].c > E[i].f)
{
dis[v] = dis[u]+E[i].cost;
pre[v] = i;
if(!in[v])
Q.push(v);
in[v] = true;
}
}
Q.pop();
in[u] = false;
}
return dis[t] != dis[N-1];
}
int Ford_Fulkerson()
{
int i,MinCost = 0;
while(Spfa())
{
int flow = INF;
for(int v=t;v!=s;v=E[i^1].v)
{
i = pre[v];
flow = min(flow,E[i].c-E[i].f);
}
for(int v=t;v!=s;v=E[i^1].v)
{
i = pre[v];
E[i].f += flow;
E[i^1].f -= flow;
MinCost += flow * E[i].cost;
}
}
return MinCost;
}