The provincial competition is coming! Maximum Flow Problem Review Learning! ! DInic

Dinic is a good algorithm, but I'm starting with the ek algorithm review

Facing the problem of maximum flow, the most impressive thing is the idea of ​​the reverse side. It provides us with the opportunity to go back. In fact, when we think about it in practice, it can be equivalent to the water on both sides flowing on this side, but the direction is different. , put it on the program, that is, add a reverse edge.

The ek algorithm is the basic algorithm, and the idea is relatively simple. It is to first use bfs to find a wave of feasible maximum flows from 1 to n, and then record the precursor of each passing node, and then call the ek algorithm to establish a reverse edge, time The above is also very time-consuming, so it is necessary to learn the Dinic algorithm and its optimized version. I will not paste the code of my ek algorithm here...

Sure enough, I learned the new from the past. I reviewed the Dinic algorithm for one night, and some have a new understanding and understanding of him. Compared with the ek algorithm, the optimization of the dinic algorithm is really very good - the current arc optimization

#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#define inf 0xfffffff
using namespace std;
const int maxn = 220;//Maximum number of nodes
const int maxm = 4e4 + 4e2;//Number of sides
int n,m;
struct node{
    int pre;
    int to,cost;
} e [maxm];
int id[maxn],cnt;
int flor[maxn];
void init()
{
    memset(id,-1,sizeof(id));
    cnt = 0;
}
int cur[maxn];
void add(int from,int to,int cost)
{
    e [cnt] .to = to;
    e[cnt].cost = cost;
    e[cnt].pre = id[from];
    id[from] = cnt++;
    swap(from,to);
    e [cnt] .to = to;
    e[cnt].cost = 0;
    e[cnt].pre = id[from];
    id[from] = cnt++;
}

 The above are all basic storage structures, chain forward star storage, establishment of reverse edges, and record of layers.

Let's take a look at the Dinic algorithm as a whole

int Dinic(int s,int t)
{
    int ret = 0;
    while(bfs(s,t))//Perform hierarchical preprocessing
    {
        for(int i = 1;i <= n;i++)
        {
            cur[i] = id[i];
        }
        ret += dfs(s,t,inf);//dfs finds the maximum augmentation path
    }
    return ret;
}

bfs performs hierarchical processing, dfs performs the search for the largest augmentation path, and cur array is a key to optimization in dfs, which will be mentioned later

Let's take a look at bfs layered processing

int bfs(int s,int t)
{
    queue<int>q;
    while(q.size())q.pop();
    memset(flor,0,sizeof(flor));
    flor[s] = 1;
    q.push(s);
    while(q.size())
    {
        int now = q.front();
        q.pop();
        for(int i = id[now];~i;i = e[i].pre)
        {
            int to = e[i].to;
            int cost = e[i].cost;
            if(flor[to] == 0/*following vis*/ && cost > 0/*and traffic*/ )
            {
                flor[to] = flor[now] + 1;
                q.push(to);
                if(to == t)return 1;//Return immediately after layering to the end
            }
        }
    }
    return 0;
}

 According to the relationship between the edges, the flor array also acts as a vis array, marking the level to prepare for the subsequent dfs. When does bfs return, it will either return 1 when it reaches the midpoint, or return 0 if it cannot reach the end point.

Wonderful time dfs, the optimization idea of ​​the current arc is too powerful

int dfs(int s,int t,int value)//Start point, end point, current flow
{
    //find augmentation path
    int ret = value;
    if(s == t || value == 0)return value;//Either the road is open, or there is no way
    int a;
    //Can't find t, because the edge traffic to t has become 0! !

    /* 
  When optimizing, record which edge is optimized to So for each edge I will only visit once */ for(int &i = cur[s];~i;i = e[i].pre) { int to = e[i].to; if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,e[i].cost)))) { e[i].cost -= a;//Optimization operation for this edge e[i^1].cost += a; ret -= a;//The last return is ret -= a, so we recorded a if(!ret)break;//ret == 0时 /* ret records the maximum flow value from s to to, a is the maximum flow from to to t When ret - a == 0, it can end, the value value is returned forward, and the subsequent edge optimization is performed */ /* Why doesn't it exit when it's not equal? ? Not equal, that is, ret > a, this is that the road ahead still has at least the residual amount of ret - a, you can continue to optimize and update dfs */ } } if(ret == value)flor[s] = 0;//The intermediate node has traversed all the edges, and the result is that there is no path (traffic), so the intermediate node s is marked as discarded return value - ret; }

 Let's put a picture of the miserable I drew first

 

That's right, at the beginning I didn't really understand the initial parameter dfs (s,t,inf) passed in inf, the first call didn't include anything, so the traffic was infinite, and it was done for the recursion. bedding

Then the conditions for the end of the recursive setting of dfs 1. found 2. The current available traffic has become zero, so there is no need to continue searching, right? ?

The current classic of arc optimization is the cur array, which is a copy of the id array, which records the edge information. The C++ reference ensures that I will only dfs the edge information of this point once, and will not repeat the dfs, which greatly saves time.

Then when a accepts the maximum flow from to to t, what does it mean when the edge and the reverse edge are updated layer by layer after returning to ret -= a? ? First, let's take a look at what ret means Therefore, when ret -= a indicates that the points from s to to are still capable of flow, if ret = 0, it cannot be flowed and returned directly. Otherwise, it can be left, and continue to perform subsequent queries according to the cur array until the query At the end, when you jump out, you can judge that if there is no one after the current point s, you can mark the point s as a fee point. The next dfs backtracking optimization will not consider the point s, and it is also a small optimization.

At this point, the Dinic algorithm comes to an end~~

——————————————————————————————————————————————————

come on! !

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324600086&siteId=291194637