Summary of network flow/cost flow topics [continuously updated]

//Fill in the hole according to the mood...

Pilot Matching Program Questions  24 Questions

Bare bipartite graph matching, just run Dinic on one side. The Hopcroft-Karp algorithm, whose principle is similar to the network flow, can reach $O( sqrt(n)* m )$ in the time complexity of the bipartite graph. 

   In fact, the principle of Dinic is similar to it, and it can run very fast in the implementation.

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pp pair<int,int>
#define rep(ii,a,b) for(auto ii=a;ii<=b;ii++)
#define	per(ii,a,b) for(auto ii=a;ii>=b;ii--)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int to [maxm], cap [maxm], nex [maxm];
int head[maxn],S,T,nume,ans,dis[maxn];
int q[maxn];
void add(int a,int b,int c){
    to [name] = b, head [name] = c, nex [name] = head [a];
    head [a] = name ++;
    to [name] = a, head [name] = 0, nex [name] = head [b];
    head[b]=nume++;
}
bool bfs(){
    memset(dis,-1,sizeof dis);
    int top=0,end=0;
    q[end++]=S;
    dis[S]=0;
    while(top!=end){
        int now=q[top++];top%=maxn;
        for(int i=head[now];~i;i=nex[i])
            if(dis[to[i]]==-1&&cap[i]){
                dis[to[i]]=dis[now]+1;
                q[end++]=to[i];end%=maxn;
            }
    }
    return dis[T]!=-1;
}
int dfs(int now,int last){
    if(now==T) return last;
    int used=0,flow;
    for(int i=head[now];~i;i=nex[i]){
        if(cap[i]&&dis[to[i]]==dis[now]+1){
            flow=last-used;
            flow=dfs(to[i],min(flow,cap[i]));
            used+=flow;
            cap[i]-=flow;
            cap[i^1]+=flow;
            if(used==last) return last;
        }
    }
    if(used==0) dis[now]=-1;
    return used;
}
void dinic(){
    years=0;
    while(bfs()) ans+=dfs(S,0x3f3f3f3f);
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
    cin>>m>>n;
    S=0;T=n+1;
    memset(head,-1,sizeof head);
    int a,b;
    while(cin>>a>>b,~a&&~b) add(a,b,1);
    for(int i=1;i<=m;i++) add(S,i,1);
    for(int i=m+1;i<=n;i++) add(i,T,1);
    dinic();
    if(ans) {
        cout<<ans<<endl;
        for(int i=0;i<nume;i+=2) if(to[i]!=S&&to[i^1]!=S&&to[i]!=T&&to[i^1]!=T&&cap[i^1]!=0){
                printf("%d %d\n",to[i^1],to[i]);
            }
    }
    else cout<<"No Solution!"<<endl;
#ifdef test
    fclose(stdin);fclose(stdout);system("out.txt");
#endif
    return 0;
}

Load Balancing Problem  24 Topics

Company G has n warehouses arranged in a circle along the railway transportation line, and each warehouse stores different quantities of goods. How to make the stock quantity of n warehouses the same with the minimum handling quantity . When moving goods, only move between adjacent warehouses.

Find the minimum handling capacity

 

The minimum cost and the maximum flow, first according to the meaning of the title, establish a circular route with a cost of 1 and a capacity of $INF$

Secondly, for those larger than the average value, it needs to be output to other warehouses, in other words, they are all small source points, then link an edge from the source point to him, the capacity is excess, and the cost is 0.

Then, correspondingly, for those smaller than the average value, it needs to be accepted, in other words, they are all small sinks, the edges linked to the sinks, the capacity is the required amount, and the cost is also 0.

Finally, run the side with the minimum cost and the maximum flow. Due to the mapping method, the outflow from the super source point must be equal to that received by the super sink.

And the outgoing warehouse will definitely not output more, and the incoming warehouse will not accept more, which meets the requirements.

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pp pair<int,int>
#define rep(ii,a,b) for(auto ii=a;ii<=b;ii++)
#define per(ii,a,b) for(auto ii=a;ii>=b;ii--)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
using namespace std;
const int maxn=10000+10;
const int maxm=10000+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
struct node {
    int pre,to,cap,cost,next;
} e [maxm];
int head[maxn],nume,inq[maxn],sum,ans;
int que [maxn], pre [maxn], dis [maxn];
int num[maxn],S,T;
inline void addedge(int a,int b,int c,int d){
    e[++nume]={a,b,c,d,head[a]};
    head [a] = name;
}
inline void add(int a,int b,int c,int d){
    addedge(a,b,c,d);addedge(b,a,0,-d);
}
bool spfa(){
    for(int i=0;i<=T;i++)dis[i]=INF;
    dis [S] = that [0] = S;
    int top=0,end=1;
    while(top!=end){
        int now=que[top++];top%=maxn;
        for(int i=head[now];i;i=e[i].next){
            if(e[i].cap&&dis[e[i].to]>dis[now]+e[i].cost){
                pre[e[i].to]=i;
                dis[e[i].to]=dis[now]+e[i].cost;
                if(!inq[e[i].to]){
                    inq[e[i].to]=true;
                    que[end++]=e[i].to;end%=maxn;
                }
            }
        }
        inq[now]=false;
    }
    return dis[T]!=INF;
}
void dfs(){
    int flow=INF;
    for(int i=pre[T];i;i=pre[e[i].pre]) flow=min(flow,e[i].cap);
    for(int i=pre[T];i;i=pre[e[i].pre]) {
        e[i].cap-=flow;
        e[i^1].cap+=flow;
        ans+=e[i].cost*flow;
    }
}
void mcf(){
    years=0;
    while(spfa()) dfs();
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
    I;
    cin>>n;
    name = 1;
    S=0,T=3*n;
    for(int i=1;i<=n;i++) cin>>num[i],sum+=num[i];
    sum/=n;
    for(int i=1;i<=n;i++) num[i]-=sum;
    for(int i=1;i<=n;i++){
        if(num[i]>0) add(S,i,num[i],0);
        else add(i+n,T,-num[i],0);
    }
    for(int i=1;i<=n;i++){
        if(i!=1){
            add(i,i-1,INF,1);
            add(i,i-1+n,INF,1);
        }
        if(i!=n){
            add(i,i+1,INF,1);
            add(i,i+1+n,INF,1);
        }
    }
    add(n,1,INF,1);
    add(n,1+n,INF,1);
    add(1,n,INF,1);
    add(1,n<<1,INF,1);
    mcf();
    cout<<ans<<endl;
#ifdef test
    fclose(stdin);fclose(stdout);system("out.txt");
#endif
    return 0;
}

pass a note

Two people exchange notes with each other on a chessboard, from top left to bottom right, the first person's note can only be right or down, and vice versa,

Each point can only pass through once, and has a weight $G(i,j)$, which requires the sum of the weights of all points that the two slips eventually pass through.

 

Maximum cost maximum flow.... But this title solution should be DP

Two people pass each other, in fact, it is equivalent to one person passing 2 to the following at the same time, so the problem is simplified,

At the beginning, I simply built the map, but it turned out that 2 CASEs were wrong.

The way is to connect a super source to $(1,1)$ with an edge with a cost of 0, a capacity of 2, and a super sink, and then use the capacity of 1. The cost is $G(i,j)$ to simulate. Finally found There may be a situation where a point passes through a stream of size 2. The problem is actually to limit the maximum flow of each point...

So.. it is a good idea to split the points. Each point is split into 2 points, one in and one out, and two edges are connected from in to out. One cost $G(i, j) $capacity is 1, one cost is 0, the capacity is 1, so even if there is a point passing through the flow of size 2, it will not cause the flow to be double-counted

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(auto ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int g[123][123];
struct node {
    int pre,to,cap,cost,next;
} e [maxm];
int head[maxn],nume,inq[maxn],sum;
int que [maxn], pre [maxn], dis [maxn];
int S,T,ans;
inline void addx(int a,int b,int c,int d){
    e[++nume]={a,b,c,d,head[a]};
    head [a] = name;
}
inline void add(int a,int b,int c,int d){
    addx(a,b,c,d);addx(b,a,0,-d);
}
bool spfa(){
    rep(i,0,T) dis[i]=-INF;
    int top=0,end=1;
    dis [S] = that [0] = 0;
    while(top!=end){
        int now=que[top++];top%=maxn;
        for(int i=head[now];i;i=e[i].next){
            if(e[i].cap&&dis[e[i].to]<dis[now]+e[i].cost){
                pre[e[i].to]=i;
                dis[e[i].to]=dis[now]+e[i].cost;
                if(!inq[e[i].to]){
                    inq[e[i].to]=true;
                    que[end++]=e[i].to;end%=maxn;
                }
            }
        }
        inq[now]=false;
    }
    return dis[T]!=-INF;
}
void dfs(){
    int d=INF;
    for(int i=pre[T];i;i=pre[e[i].pre]) d=min(d,e[i].cap);
    for(int i=pre[T];i;i=pre[e[i].pre]) {
        e [i] .cap- = d;
        e [i ^ 1]. cap + = d;
        ans+=e[i].cost*d;
    }
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
		I;
    cin>>n>>m;
    rep(i,1,n){
        rep(j,1,m){
            cin>>g[i][j];
        }
    }
    S=0,T=3*n*m;
    int gap=n*m+2;
    name = 1;
    add(S,1,2,0);
    add(m*n,T,2,0);
    rep(i,1,n){
        rep(j,1,m){
            int s=(i-1)*m+j;
            if(j<m||i<n){
								if(i==1&&j==1) add(s,s+gap,2,0);
                else add(s,s+gap,1,g[i][j]);
                if(j<m) add(s+gap,s+1,1,0);
                if(i<n) add(s+gap,s+m,1,0);
            }
        }
    }
    years=0;
    while(spfa()) {
        dfs();
    }
    cout<<abs(ans)<<endl;
#ifdef test
    fclose(stdin);fclose(stdout);system("out.txt");
#endif
    return 0;
}

  

Guess you like

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