POJ3436 http://www.bubuko.com/infodetail-1013321.html
const int N = 1000;
struct Edge{
int from,to,cap,flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct Dinic{
int n,m,s,t;//结点数,边数(包括反向弧),源点编号,汇点编号
vector<Edge>edges;//边表,dges[e]和dges[e^1]互为反向弧
vector<int>G[N];//邻接表,G[i][j]表示结点i的第j条边在e数组中的编号
bool vis[N]; //BFS的使用
int d[N]; //从起点到i的距离
int cur[N]; //当前弧下标
void Init(int n) {
this->n = n;
for (int i = 0; i <= n; i++) {
G[i].clear();
}
edges.clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool 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=edges[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)//x表示当前结点,a表示目前为止的最小残量
{
if(x==t||a==0)return a;//a等于0时及时退出,此时相当于断路了
int flow=0,f;
for(int&i=cur[x];i<G[x].size();i++)//从上次考虑的弧开始,注意要使用引用,同时修改cur[x]
{
Edge&e=edges[G[x][i]];//e是一条边
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)break;//a等于0及时退出,当a!=0,说明当前节点还存在另一个曾广路分支。
}
}
return flow;
}
int Maxflow(int s,int t)//主过程
{
this->s=s,this->t=t;
int flow=0;
while(bfs())//不停地用bfs构造分层网络,然后用dfs沿着阻塞流增广
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
};
struct Dinic{
int n,m,s,t;//结点数,边数(包括反向弧),源点编号,汇点编号
vectoredges;//边表,dges[e]和dges[e^1]互为反向弧
vectorG[N];//邻接表,G[i][j]表示结点i的第j条边在e数组中的编号
bool vis[N]; //BFS的使用
int d[N]; //从起点到i的距离
int cur[N]; //当前弧下标
void Init(int n) {
this->n = n;
for (int i = 0; i <= n; i++) {
G[i].clear();
}
edges.clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool 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=edges[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)//x表示当前结点,a表示目前为止的最小残量
{
if(x==t||a==0)return a;//a等于0时及时退出,此时相当于断路了
int flow=0,f;
for(int&i=cur[x];i<G[x].size();i++)//从上次考虑的弧开始,注意要使用引用,同时修改cur[x]
{
Edge&e=edges[G[x][i]];//e是一条边
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)break;//a等于0及时退出,当a!=0,说明当前节点还存在另一个曾广路分支。
}
}
return flow;
}
int Maxflow(int s,int t)//主过程
{
this->s=s,this->t=t;
int flow=0;
while(bfs())//不停地用bfs构造分层网络,然后用dfs沿着阻塞流增广
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
};
链式前向星的Dinic
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#define M 400
int INF=10000001;
using namespace std;
struct node
{
int u,v,cap,next;
};
node edge[M*M];
int next[M],head[M],d[M],vis[M];
int ecnt;
void init()
{
ecnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int c)
{
edge[ecnt].u=v;
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++)d[i]=-1;
d[begin]=0;
queue<int> q;
q.push(begin);
while(!q.empty())
{
k=q.front();
q.pop();
for(i=head[k];i!=-1;i=edge[i].next)
{
y=edge[i].v;
if(edge[i].cap>0 && d[y]==-1)
{
d[y]=d[k]+1;
if(y==end)return true;
q.push(y);
}
}
}
return false;
}
int dfs(int x,int exp,int end)
{
vis[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 && d[y]==d[x]+1 && vis[y]==0)
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(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++)vis[i]=0;
flow=dfs(begin,INF,end);
if(flow==0)break;
ans+=flow;
}
}
return ans;
}
int main()
{ int i,n,m;
while(~scanf("%d%d",&m,&n))
{ init();
for(i=1;i<=m;i++)
{ int u,v,c;
scanf("%d%d%d",&u,&v,&c);
add(u,v,c);
}
int sum=dinic(1,n);
printf("%d\n",sum);
}
return 0;
}
最大流 Dinic 算法
struct edge {
int to, cap, rev;
};
vector<edge> G[N];
int level[N];
int iter[N];
void add_edge(int from, int to, int cap)
{
G[from].push_back((edge){to, cap, G[to].size()});
G[to].push_back((edge){from, 0, G[from].size() - 1});
}
bool bfs(int s, int t)
{
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while (que.size()) {
int v = que.front();
que.pop();
for (int i = 0; i < G[v].size(); i++) {
edge e = G[v][i];
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
return level[t] != -1;
}
int dfs(int v, int t, int f)
{
if (v == t)
return f;
for (int &i = iter[v]; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int maxflow(int s, int t)
{
int flow = 0;
while (bfs(s, t)) {
memset(iter, 0, sizeof(iter));
int f;
while ((f = dfs(s, t, inf)) > 0)
flow += f;
}
return flow;
}
最大流 EK 算法
int path[N];
int a[N];
struct edge {
int from, to, flow, cap;
edge(int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) {}
};
vector<edge> E;
vector<int> G[N];
void add_edge(int from, int to, int cap)
{
E.push_back(edge(from, to, cap, 0));
E.push_back(edge(to, from, 0, 0));
int q = E.size();
G[from].push_back(q - 2);
G[to].push_back(q - 1);
}
int maxflow()
{
int flow = 0;
for (;;) {
memset(a, 0, sizeof(a));
a[s] = inf;
queue<int> que;
que.push(s);
while (!que.empty()) {
int now = que.front();
que.pop();
for (int i = 0; i < G[now].size(); i++) {
edge &e = E[G[now][i]];
if (!a[e.to] && e.cap > e.flow) {
path[e.to] = G[now][i];
a[e.to] = min(a[now], e.cap - e.flow);
que.push(e.to);
}
}
if (a[t])
break;
}
if (!a[t])
break;
for (int i = t; i != s; i = E[path[i]].from) {
E[path[i]].flow += a[t];
E[path[i] ^ 1].flow -= a[t];
}
flow += a[t];
}
return flow;
}
最大流 ISAP 算法
struct Edge {
int from, to, cap, flow;
Edge() {}
Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow) {}
};
struct ISAP {
int p[N], num[N], cur[N], d[N];
int t, s, n, m;
bool vis[N];
vector<int> G[N];
vector<Edge> edges;
void init(int n) {
this->n = n;
for (int i = 0; i <= n; i++) {
G[i].clear();
d[i] = INF;
}
edges.clear();
}
void AddEdge(int from, int to, int cap) {
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
d[t] = 0;
vis[t] = 1;
Q.push(t);
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (int i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i] ^ 1];
if (!vis[e.from] && e.cap > e.flow) {
vis[e.from] = true;
d[e.from] = d[u] + 1;
Q.push(e.from);
}
}
}
return vis[s];
}
int Augment() {
int u = t, flow = INF;
while (u != s) {
Edge &e = edges[p[u]];
flow = min(flow, e.cap - e.flow);
u = edges[p[u]].from;
}
u = t;
while (u != s) {
edges[p[u]].flow += flow;
edges[p[u] ^ 1].flow -= flow;
u = edges[p[u]].from;
}
return flow;
}
int Maxflow(int s, int t) {
this->s = s; this->t = t;
int flow = 0;
BFS();
if (d[s] >= n)
return 0;
memset(num, 0, sizeof(num));
memset(cur, 0, sizeof(cur));
for (int i = 0; i < n; i++)
if (d[i] < INF)
num[d[i]]++;
int u = s;
while (d[s] < n) {
if (u == t) {
flow += Augment();
u = s;
}
bool ok = false;
for (int i = cur[u]; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[u] == d[e.to] + 1) {
ok = true;
p[e.to] = G[u][i];
cur[u] = i;
u = e.to;
break;
}
}
if (!ok) {
int Min = n - 1;
for (int i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow)
Min = min(Min, d[e.to]);
}
if (--num[d[u]] == 0)
break;
num[d[u] = Min + 1]++;
cur[u] = 0;
if (u != s)
u = edges[p[u]].from;
}
}
return flow;
}
};