P3376 Network maximum flow template (Dinic + dfs multiple augmented optimization optimization + + fried point arc current optimization)

### P3376 topic Link ###

Here to talk about the implement three optimized and correctness.

 

1, dfs multiple augmented optimization

General Dinic algorithm is this, bfs () is used to mark a number of augmenting paths that can once bfs () the multiple dfs () augmenting paths. There will be a while (bfs ()) once, then dfs () n times, n augmenting the road.

So optimize our dfs is to make a dfs () directly accumulate the bfs this time marked out n augmenting Road (). Becomes while (bfs ()) then dfs () once.

General Dinic algorithm:

int dfs(int u,int res)
{
    if(u==T) return res;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(flag[v]==flag[u]+1&&edge[i].val){
            if(int k=dfs(v,min(res,edge[i].val))){
                edge[i].val-=k;
                edge[i^1].val+=k;
                return k;
            }
        }
    }
    return 0;
}

Here's return k ensures that each time dfs () at the finish T, the first augmented road traffic k, then return ended the dfs ().

Then we need to do is make dfs () to search all augmenting paths after the return.

In this way you can, we express the flow of the current point've ever experienced with nowflow. We see the figure, for example, now u == 2 1 ---> 2 flow rate is limited to 10, then every time you return to the point u, u can point through traffic can not be greater than 10, otherwise the road will not become augmenting paths. Then use the cumulative flow rate u to nowflow point, once nowflow equal to 10, then the path will no longer be augmented extending from point u, it can break.

For min of flow - nowflow, to tell where the total flow to all points behind u not exceed flow - nowflow, i.e. maximum flow point u can carry.

Then for the issue of the return value: the need to return traffic to the site. The reason is because, if the point spread is finished, then the traffic has returned to the point until you return to the starting point nowflow S, then at this time nowflow says the bfs () flow all augmenting paths could find with.

int dfs(int u,int flow)
{
    int nowflow=0;
    if(u==T) return flow;
    for(int i=head[u];i!=-1;i=edge[i].next){
        cur[u]=i;
        int v=edge[i].to;
        if(d[v]==d[u]+1&&edge[i].val>0){
            if(int k=dfs(v,min(flow-nowflow,edge[i].val))){
                edge[i].val-=k;
                Edge [I^ . 1 ] .val + = K; 
                nowflow + = K;
                 IF (nowflow == Flow) BREAK ; 
            } 
        } 
    } 
    return nowflow; // It should return the total flow rate of the point 
}

 

2, fried point optimization

If the current point u discovered after this stretching point has no augmenting path is found, i.e. the current point nowflow, then the possible augmenting path extending through the point, so that this directly to the point "blasted" off, i.e., D [u ] = -1.

int dfs(int u,int flow)
{
    int nowflow=0;
    if(u==T) return flow;
    for(int i=head[u];i!=-1;i=edge[i].next){
        cur[u]=i;
        int v=edge[i].to;
        if(d[v]==d[u]+1&&edge[i].val>0){
            if(int k=dfs(v,min(flow-nowflow,edge[i].val))){
                edge[i].val-=k;
                edge[i^1].val+=k;
                nowflow+=k;
                if(nowflow==flow) break;
            }
        }
    }
    if(!nowflow) d[u]=-1; // 炸点
    return nowflow;
}

 

3, optimization of the current arc

For once bfs looking for (after) augmenting path, a number when asked if a way is a, it will no longer be augmented by this road.

For example, here the beginning has been augmented by 1 → 2 → 3, the cumulative flow. So next time when traversing point 2, 2 → 3 road traffic is no longer provided, so you can directly ruled out (of course, it may take 3 → 2 corresponding reverse side of this, id anyway edge is not Like, did not affect)

We will use CUR [u] to represent the sequence number of the last edge extends to the current point u, then the next time point u to traverse directly from traversing edges.

int dfs(int u,int flow)
{
    int nowflow=0;
    if(u==T) return flow;
    for(int i=cur[u];i!=-1;i=edge[i].next){
        cur[u]=i; // 当前弧优化
        int v=edge[i].to;
        if(d[v]==d[u]+1&&edge[i].val>0){
            if(int k=dfs(v,min(flow-nowflow,edge[i].val))){
                edge[i].val-=k;
                edge[i^1].val+=k;
                nowflow+=k;
                if(nowflow==flow) break;
            }
        }
    }
    if(!nowflow) d[u]=-1;
    return nowflow;
}

 

Optimization of these three would make a lot of time complexity reduction Dinic, here the test is a direct drop nearly 300 MS.

Total code is as follows:

#define IO freopen("test.in","r",stdin),freopen("test.out","w",stdout)
#define inf 0x3f3f3f3f
#define lson root<<1
#define rson root<<1|1
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define maxn 10008
#define inf 0x3f3f3f3f
int N,M,S,T,cnt;
int head[maxn],cur[maxn],d[maxn];
inline int read()
{
    int x=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return w?-x:x;
}
struct Edge
{
    int to;
    int val;
    int next;
}edge[200008];
inline void add(int u,int v,int w)
{
    edge[++cnt].to=v;
    edge[cnt].val=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
bool bfs()
{
    queue<int> q;
    while(!q.empty()) q.pop();
    for(int i=1;i<=N;i++) d[i]=-1;
    d[S]=0;
    q.push(S);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(d[v]==-1&&edge[i].val>0){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[T]!=-1;
}
int dfs(int u,int flow)
{
    int nowflow=0;
    if(u==T) return flow;
    for(int i=cur[u];i!=-1;i=edge[i].next){
        cur[u]=i;
        int v=edge[i].to;
        if(d[v]==d[u]+1&&edge[i].val>0){
            if(int k=dfs(v,min(flow-nowflow,edge[i].val))){
                edge[i].val-=k;
                edge[i^1].val+=k;
                nowflow+=k;
                if(nowflow==flow) break;
            }
        }
    }
    if(!nowflow) d[u]=-1;
    return nowflow;
}
int Dinic()
{
    int ans=0;
    while(bfs())
    {
        for(int i=1;i<=N;i++) cur[i]=head[i];
        ans+=dfs(S,inf);
    }
    return ans;
}
int main()
{
    //IO;
    N=read(),M=read(),S=read(),T=read();
    int A,B,C;
    cnt=-1;
    for(int i=1;i<=N;i++) head[i]=-1;
    while(M--)
    {
        A=read(),B=read(),C=read();
        add(A,B,C),add(B,A,0);
    }
    printf("%d\n",Dinic());
}

 

Guess you like

Origin www.cnblogs.com/Absofuckinglutely/p/11520363.html