增广路的核心就是引入了反向边,使在进行道路探索选择的时候增加了类似于退路的东西【有一点dp的味道??】
具体操作就是:1、首先使用结构体以及数组链表next[ MAXN ]进行边信息的存储
2、【核心】在存储正向边时,将正向边结构体数组相邻编号的元素存储反向边
【具体操作:如正向边为AA[0],则对应的反向边为AA[1],这样就可以在之后通过异或来对正向边对应的反向边进行更新】【初始时反向边的容量为0】
3、通过dfs进行寻路,寻路过程要用数组记录下来路经过的边的编号,便于在找到终点后遍历找边的最小剩余容量,然后在总流量上加上最小的剩余容量即可
4、【易错】dfs应该写成bool 型的,在找到一条路或找不到路之后直接return【而不是一直dfs到最后】,而且要在主函数中加一个for(;;),在bool dfs 返回值为false时跳出循环即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 10000+10 5 #define M 10000+10 6 #define inf 1e9; 7 using namespace std; 8 int head[N],arnum=1,used[N],ans,way[M]; 9 struct ss{int next,to,cap;}a[M]; 10 void add(int from,int to,int cap){a[++arnum]=(ss){head[from],to,cap};head[from]=arnum;} 11 void insert(int u,int v,int cap){add(u,v,cap),add(v,u,0);} 12 int n,m,S,T; 13 void work(int step) 14 { 15 int minn=inf; 16 for(int i=1;i<=step;i++) 17 minn=min(minn,a[way[i]].cap); 18 ans+=minn; 19 for(int i=1;i<=step;i++) 20 { 21 a[way[i]].cap-=minn; 22 a[way[i]^1].cap+=minn; 23 } 24 } 25 int dfs(int u,int step) 26 { 27 for(int i=head[u];i;i=a[i].next) 28 { 29 int v=a[i].to; 30 int cap=a[i].cap; 31 if(not used[v] and cap>0) 32 { 33 way[step]=i; 34 used[v]=1; 35 if(v==T){work(step);return 1;} 36 else if(dfs(v,step+1))return 1; 37 } 38 return 0; 39 } 40 } 41 int main() 42 { 43 scanf("%d%d%d%d",&n,&m,&S,&T); 44 int u,v,c; 45 for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&c);insert(u,v,c);} 46 for(;;) 47 { 48 memset(used,0,sizeof(used)); 49 used[S]=1; 50 if(not dfs(S,1))break; 51 } 52 printf("%d",ans); 53 return 0; 54 }