Dinic

裸版:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

const int MAX_NODE_NUM = 100;
const int MAX_EDGE_NUM = 5000;

struct Edge {
  int to;
  int flow;
  int next;
} edge[(MAX_EDGE_NUM << 1) + 1];

int first[MAX_NODE_NUM + 1];
int depth[MAX_NODE_NUM + 1];
int now_edge[MAX_NODE_NUM + 1];
int start;
int end;

void addEdge(const int, const int, const int);
long long maxFlow(int);

int main() {
  //init
  memset(first, -1, sizeof(first));
  int noden;
  int edgen;
  scanf("%d%d%d%d", &noden, &edgen, &start, &end);
  while(edgen--) {
    int from, to, flow;
    scanf("%d%d%d", &from, &to, &flow);
    addEdge(from, to, flow);
  }
  ///init

  //solve&print
  printf("%lld\n", maxFlow(noden));
  ///solve&print
}

inline void addEdge(const int from, const int to, const int flow) {
  static int cnt = -1;
  edge[++cnt].to = to;
  edge[cnt].flow = flow;
  edge[cnt].next = first[from];
  first[from] = cnt;
  edge[++cnt].to = from;
  edge[cnt].flow = 0;
  edge[cnt].next = first[to];
  first[to] = cnt;
  return;
}

bool setDepth() {
  std::queue<int> que;
  while(!que.empty()) que.pop();
  memset(depth, 0, sizeof(depth));
  depth[start] = 1;
  que.push(start);
  while(!que.empty()) {
    int now = que.front();
    que.pop();
    for(int edg = first[now]; edg != -1; edg = edge[edg].next) {
      if(edge[edg].flow > 0 && depth[edge[edg].to] == 0) {
        depth[edge[edg].to] = depth[now] + 1;
        que.push(edge[edg].to);
      }
    }
  }
  return depth[end] != 0;
}

long long dfs(int now, long long flow) {
  if(now == end) {
    return flow;
  }
  long long res = 0;
  for(int edg = now_edge[now]; edg != -1; edg = edge[edg].next) {
    now_edge[now] = edg;
    if(depth[edge[edg].to] != depth[now] + 1) continue;
    if(edge[edg].flow <= 0) continue;
    long long add = dfs(edge[edg].to, std::min(flow, (long long)edge[edg].flow));
    edge[edg].flow -= add;
    edge[edg ^ 1].flow += add;
    flow -= add;
    res += add;
    if(flow == 0) break;
  }
  if(res == 0) {
    depth[now] = 0;
  }
  return res;
}

long long maxFlow(int noden) {
  long long res = 0;
  while(setDepth()) {
    for(int i = 1; i <= noden; ++i) {
      now_edge[i] = first[i];
    }
    res += dfs(start, 0x7fffffffffffffffll);
  }
  return res;
}

后来写的好看点的:

class Dinic {
 private:
  struct Node {
    Node() : first(-1) {}
    int first;
    int nowEdge;
    int depth;
  };
  struct Edge {
    Edge(int to, long long flow, int next) : to(to), flow(flow), next(next) {}
    int to;
    long long flow;
    int next;
  };
  bool makeDepth(int start, int end) {
    for(int i = 0; i < node.size(); ++i) {
      node[i].depth = 0x7fffffff;
    }
    node[start].depth = 0;
    std::queue<int> que;
    que.push(start);
    while(!que.empty()) {
      int now = que.front();
      que.pop();
      for(int i = node[now].first; ~i; i = edge[i].next) {
        if(edge[i].flow <= 0) continue;
        if(node[edge[i].to].depth != 0x7fffffff) continue;
        node[edge[i].to].depth = node[now].depth + 1;
        que.push(edge[i].to);
      }
    }
    return node[end].depth != 0x7fffffff;
  }
  long long dfs(int now, long long flow, int end) {
    if(now == end) return flow;
    long long res = 0;
    for(int &i = node[now].nowEdge; ~i; i = edge[i].next) {
      if(node[edge[i].to].depth != node[now].depth + 1) continue;
      if(edge[i].flow == 0) continue;
      long long delta = dfs(edge[i].to, std::min(flow, edge[i].flow), end);
      edge[i].flow -= delta;
      edge[i ^ 1].flow += delta;
      flow -= delta;
      res += delta;
    }
    if(res == 0) {
      node[now].depth = 0;
    }
    return res;
  }
  std::vector<Node> node;
  std::vector<Edge> edge;
 public:
  int newNode() {
    Node temp;
    node.push_back(temp);
    return node.size() - 1;
  }
  void addEdge(int from, int to, long long flow) {
    edge.push_back(Edge(to, flow, node[from].first));
    node[from].first = edge.size() - 1;
    edge.push_back(Edge(from, 0, node[to].first));
    node[to].first = edge.size() - 1;
  }
  long long maxFlow(int start, int end) {
    long long ret = 0;
    while(makeDepth(start, end)) {
      for(int i = 0; i < node.size(); ++i) {
        node[i].nowEdge = node[i].first;
      }
      ret += dfs(start, 0x7fffffffffffffffll, end);
    }
    return ret;
  }
};