网络流初步:<最大流>——核心(增广路算法)(模板)

增广路的核心就是引入了反向边,使在进行道路探索选择的时候增加了类似于退路的东西【有一点dp的味道??】

具体操作就是:1、首先使用结构体以及数组链表next[ MAXN ]进行边信息的存储

2、【核心】在存储正向边时,将正向边结构体数组相邻编号的元素存储反向边

  【具体操作:如正向边为AA[0],则对应的反向边为AA[1],这样就可以在之后通过异或来对正向边对应的反向边进行更新】【初始时反向边的容量为0】

3、通过dfs进行寻路,寻路过程要用数组记录下来路经过的边的编号,便于在找到终点后遍历找边的最小剩余容量,然后在总流量上加上最小的剩余容量即可

4、【易错】dfs应该写成bool 型的,在找到一条路或找不到路之后直接return【而不是一直dfs到最后】,而且要在主函数中加一个for(;;),在bool dfs 返回值为false时跳出循环即可

 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 }
View Code

 

posted @ 2018-04-17 17:37  MekakuCityActor  阅读(234)  评论(0编辑  收藏  举报