struct Edge
{
int from,to,cap,flow;
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);
}
};
struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
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)
{
if(x==t || a==0)
return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();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 Maxflow(int s,int t)
{
this->s=s,this->t=t;
int flow=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
};
伪代码
下面是dfs的过程:
[c-sharp]
view plain
copy
- ps;
- While outdegree(s)>0
- up.top;
- if u<>t
- if outdegree(u)>0
- 设(u,v)为层次图中的一条边;
- pp,v;
- else
- 从p和层次图中删除点u,
- 以及和u连接的所有边;
- else
- 增广p(删除了p中的饱和边);
- 令p.top为p中从s可到达的最后顶点;
- end while
[c-sharp]
view plain
copy
- ps;
- While outdegree(s)>0
- up.top;
- if u<>t
- if outdegree(u)>0
- 设(u,v)为层次图中的一条边;
- pp,v;
- else
- 从p和层次图中删除点u,
- 以及和u连接的所有边;
- else
- 增广p(删除了p中的饱和边);
- 令p.top为p中从s可到达的最后顶点;
- end while
在程序里,p表示找到的增广路径,p.top为路径中的最后一个顶点。一开始,p中只有源点。
整个While循环分为2个操作。如果p的最后一个顶点为汇点,也就是说找到了增广路,那么对p增广,注意到增广后一定有一条或多条p中的边被删除了。这时,我们使增广路径后退至p中从源点可到达的最后一个顶点。
如果p的最后一个顶点不为汇点,那么观察最后那个的顶点u 。若在层次图中存在从u连出的一条边,比如(u,v),我们就将顶点v放入路径p中,继续dfs遍历;否则,点u对之后的dfs遍历就没有用了,我们将点u以及层次图中连到u的所有边删除,并且在p中后退一个点。
Dfs过程将会不断重复这2个操作,直到从源点连出的边全部被删除为止。
nocow
bool build()//建立层次图
{
int x,y;
memset(d,-1,sizeof(d));
memset(G,-1,sizeof(G));
bg=ed=d[s]=0;Q[ed++]=s;G[s]=g[s];
while(bg<ed)
{
x=Q[bg++];
for(int i=g[x];i+1;i=np[i])
{
y=to[i];
if(cap[i]&&d[y]==-1)
{
d[y]=d[x]+1;G[y]=g[y];
if(y==t)return true;
Q[ed++]=y;
}
}
}
return false;
}
int find(int x,int low=inf)//进行增广
{
if(x==t)return low;
int ret=0,y;
for(int &i=G[x];i+1;i=np[i])//注意i是引用
{
y=to[i];
if(cap[i] && d[y]==d[x]+1 && (ret=find(y,low<?cap[i])))
{
cap[i]-=ret;cap[vp[i]]+=ret;
return ret;
}
}
return 0;
}
int dinic()//主过程
{
int flow;
while(build())
while(flow=find(s))
cnt+=flow;
return 0;
}
非递归
//Author: dd_engi
void Dinic()
{
for(;;){
BFS();
if(D[T]==-1)break;
int path_n=0;
int x=S;
memcpy(cur,E,sizeof(cur));
for(;;){
if(x==T){
int mink=-1,delta=INT_MAX;
for(int i=0;i<path_n;++i){
if(path[i]->c<delta){
delta=path[i]->c;
mink=i;
}
}
for(int i=0;i<path_n;++i){
path[i]->c-=delta;
path[i]->back->c+=delta;
}
path_n=mink;
x=path[path_n]->x;
}
edge* e;
for(e=cur[x];e;e=e->next){
if(e->c==0)
continue;
int y=e->y;
if(D[x]+1==D[y])
break;
}
cur[x]=e;
if(e){
path[path_n++]=e;
x=e->y;
}
else{
if(path_n==0)
break;
D[x]=-1;
--path_n;
x=path[path_n]->x;
}
}
}
}