Get started easily with network streaming

The following is for my own understanding. Every giant is optimistic about the novel. If there is any mistake, please point out that the crab ~
water flows out of the source and gathers in the sink. Imagine many intertwined creeks flowing from the source and converging into the sea at the other end. The problem described by the network flow is that the width of the creeks flowing in is different. In other words, it is segmented flow restriction. Assuming the amount of water flowing into the source It is infinite. Ask the water source how much water can converge to the sea once infinite water is poured into it?
The Soul Painter is on the stage.
Insert picture description here
If you want to calculate by hand, you must find it from the very beginning, try every possible stream, and get the biggest result in the end.
The same is true for computers. Every possible stream is officially called "Zhengguang Road". The simplest network flow should be the EK algorithm. This kind of algorithm is to search for the Zengguang Road every time and add the answer. Jiangzi, and the so-called dinic algorithm, uses bfs to find the augmentation road, plus arc optimization, explosion point optimization, etc., can run fast. It is said that it can run 1e6? The
deep part is after finding the augmentation road, How to deal with the road, here is also the most difficult place to understand. In fact, after finding each augmented road, the effective result is the narrowest part of the road, which is to make all sides of the road reduce the most. In the narrow place, what remains is the residual current, which can be used by other Zengguang roads~ But, the selection of Zengguang road will definitely result in different results, so we have to give the computer a chance to regret it, because If you don't give it, the first place you choose may not be the best one, so you have to build a reverse edge with a weight of 0.
Post a dinic board here.

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-5
#define rint register int
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
    
    
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    
     if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') {
    
     res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int INF = 2e9;
const int N = 1e4+4;
const int M = 2e5+5;
const LL Mod = 1e9+7;
struct xx {
    
    
  int next, to, w;
}edge[M];
//记得tot要置为1噢~方便后面计算啦,就不用初始化head数组啦
int tot = 1, head[N];
void Add(int u, int v, int w) {
    
    
  edge[++tot] = xx {
    
    head[u], v, w};
  head[u] = tot;
}
int n, m, s, t;
int dep[N];
int bfs() {
    
     //找增广路
  memset(dep, 0, sizeof dep);
  queue<int> q;
  while(!q.empty()) q.pop();
  q.push(s); dep[s] = 1;
  while(!q.empty()) {
    
    
    int u = q.front(); q.pop();
    for(int i = head[u], v; i; i = edge[i].next) {
    
    
      v = edge[i].to;
      if(edge[i].w && !dep[v]) {
    
    
        dep[v] = dep[u] + 1; q.push(v);
      }
    }
  }
  return dep[t]; //如果汇点没有被更新到就是0啦~
}
//这里就是深入的部分啦,是对每条增广路的处理
int dfs(int u, int in) {
    
     
  if(u == t) return in;
  int out = 0;
  for(int i = head[u], v; i && in; i = edge[i].next) {
    
    
    v = edge[i].to;
    if(dep[v] == dep[u] + 1 && edge[i].w) {
    
    
      //min过程就是找这条增广路的最窄部分啦
      int x = dfs(v, min(in, edge[i].w));
      in -= x; edge[i].w -= x;
      //反向边啦,i^1是访问反向边啦(tot要初始1噢)
      out += x; edge[i^1].w += x;
    }
  }
  if(!out) dep[u] = 0; //强有力的炸点优化
  return out;
}
int dinic() {
    
    
  int res = 0;
  while(bfs()) {
    
    
    res += dfs(s, INF);
  }
  return res;
}
int main() {
    
    
  scanf("%d%d%d%d", &n, &m, &s, &t);
  for(int i = 0, u, v, w; i < m; ++i) {
    
    
    scanf("%d%d%d", &u, &v, &w);
    Add(u, v, w); Add(v, u, 0);
  }
  printf("%d\n", dinic());
  return 0;
}

Finally, I recommend a place where I learn to learn online cows~

Detailed network flow

[Algorithm Lecture] [University of Electronic Science and Technology of China] [ACM] Introduction to Network Streaming

Guess you like

Origin blog.csdn.net/qq_43408978/article/details/105998365