当前弧优化
我们通过上一篇博客 传送门 知道,每一次bfs之后都跟着若干次dfs。每一次dfs都会发现一条可行流,而且这个可行流肯定是该路径的最大可行流。所以我们对于一条路径进行增广之后,肯定不用进行第二次增广。
所以我们这里加了一个优化,在同一个 bfs分层后跟着的dfs里面,加入要 遍历编号为1、3、5、7、9的五条边,我们默认
cur[i]=1
c
u
r
[
i
]
=
1
,然后我们从
cur[i]
c
u
r
[
i
]
开始找,假如在编号为5的边后面找了一条,那么我们可以肯定,该次dfs之后,编号为1、3、5的边肯定都已经不能再进行增广了,因此
cur[i]=7
c
u
r
[
i
]
=
7
,下一次dfs直接从编号为 7的点继续。
注意点:进行了新一轮的bfs之后,一定要给
cur
c
u
r
数组初始化,也就是
cur[i]=head[i]
c
u
r
[
i
]
=
h
e
a
d
[
i
]
code
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int num=0;char c=' ';bool flag=true;
for(;c>'9'||c<'0';c=getchar())
if(c=='-')
flag=false;
for(;c>='0'&&c<='9';num=(num<<3)+(num<<1)+c-48,c=getchar());
return flag ? num : -num;
}
const int maxn=10020;
const int maxm=100020;
namespace graph{
struct node{
int dot,val,next;
}a[maxm*2];
int n,m,s,t;
int head[maxn],top=0;
void insert(int x,int y,int v){
a[top].dot=y;
a[top].val=v;
a[top].next=head[x];
head[x]=top++;
}
void init(){
n=read();
m=read();
s=read();
t=read();
memset(head,-1,sizeof head);
for(int i=1;i<=m;i++){
int x=read();
int y=read();
int v=read();
insert(x,y,v);
insert(y,x,0);
}
}
}using namespace graph;
namespace Flow{
int d[maxn],cur[maxn];
bool bfs(){
memset(d,0,sizeof d);
queue<int>q;
q.push(s);d[s]=1;
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i!=-1;i=a[i].next){
int y=a[i].dot;
if(a[i].val&&!d[y]){
q.push(y);
d[y]=d[x]+1;
if(y==t)return true;
}
}
}
return false;
}
int dfs(int x,int flow){
if(x==t)
return flow;
for(int &i=cur[x];i+1;i=a[i].next){
//这边采用地址引用,i更改cur也更改
int y=a[i].dot;
if(d[y]==d[x]+1 && a[i].val!=0){
int k=dfs(y,min(a[i].val,flow));
if(k){
a[i].val-=k;
a[i^1].val+=k;
return k;
}
}
}
return 0;
}
}using namespace Flow;
const int INF=2e9;
void dinic(){
int flow=0;
int maxflow=0;
while(bfs()){
for(int i=1;i<=n;i++)cur[i]=head[i];//注意点在这
while(flow=dfs(s,INF))maxflow +=flow;
}
printf("%d\n",maxflow);
}
int main(){
init();
dinic();
return 0;
}