zoukankan      html  css  js  c++  java
  • 最大流模板

      1 /*
      2  *最大流模板(引用学长的模板。。。)
      3  * SAP(当前弧优化+GAP优化)非递归形式  7  */
      8 
      9 #include <cstring>
     10 #include <iostream>
     11 #include <cstdio>
     12 
     13 #define SETZR(a) memset(a,0,sizeof(a))
     14 
     15 using namespace std;
     16 
     17 //定义常量:边数、点数和无穷
     18 const int MAXM = 1000000;
     19 const int MAXN = 10000;
     20 const int INF = 1000000000;
     21 
     22 //边的结构体
     23 //此模板中图以池子法存储
     24 
     25 struct record {
     26     int v, f, next;
     27 } edge[MAXM];
     28 
     29 /*
     30  * 变量说明:
     31  * pointer为各点出度头指针
     32  * dis为距离标号
     33  * vh记录每个距离标号点的数量,用于GAP优化
     34  * his记录各点入栈时的流量,用于退栈
     35  * di记录各点当前弧
     36  * pre记录各点前驱结点,同样用于退栈
     37  */
     38 int n, m, s, t, cas, cl;
     39 int pointer[MAXN], dis[MAXN], vh[MAXN];
     40 int his[MAXN], di[MAXN], pre[MAXN];
     41 
     42 void connect(int a, int b, int f) {
     43     cl++;
     44     edge[cl].next = pointer[a];
     45     edge[cl].v = b;
     46     edge[cl].f = f;
     47     pointer[a] = cl;
     48     cl++;
     49     edge[cl].next = pointer[b];
     50     edge[cl].v = a;
     51     edge[cl].f = 0; //若为无向边,则f = f
     52     pointer[b] = cl;
     53 }
     54 
     55 int main() {
     56     scanf("%d", &cas);
     57     while (cas--) {
     58         scanf("%d%d%d%d", &n, &m, &s, &t);
     59         //初始化
     60         cl = 1;
     61         SETZR(dis);
     62         SETZR(vh);
     63         SETZR(pointer);
     64         //建图
     65         for (int i = 0; i < m; i++) {
     66             int p, k, w;
     67             scanf("%d%d%d", &p, &k, &w);
     68             connect(p, k, w);
     69         }
     70         //最大流过程
     71         vh[0] = n; //初始化GAP数组(默认所有点的距离标号均为0,则距离标号为0的点数量为n)
     72         for (int i = 0; i < n; i++) di[i] = pointer[i]; //初始化当前弧
     73         int i = s, aug = INF, flow = 0; //初始化一些变量,flow为全局流量,aug为当前增广路的流量
     74         bool flag = 0; //标记变量,记录是否找到了一条增广路(若没有找到则修正距离标号)
     75         while (dis[s] < n) {
     76             his[i] = aug; //保存当前流量
     77             flag = 0;
     78             int p = di[i];
     79             while (p != 0) {
     80                 if ((edge[p].f > 0) && (dis[edge[p].v] + 1 == dis[i])) {//利用距离标号判定可行弧
     81                     flag = 1; //发现可行弧
     82                     di[i] = p; //更新当前弧
     83                     aug = min(aug, edge[p].f); //更新当前流量
     84                     pre[edge[p].v] = p; //记录前驱结点
     85                     i = edge[p].v; //在弧上向前滑动
     86                     if (i == t) {//遇到汇点,发现可增广路
     87                         flow += aug; //更新全局流量
     88                         while (i != s) {//减少增广路上相应弧的容量,并增加其反向边容量
     89                             edge[pre[i]].f -= aug;
     90                             edge[pre[i]^1].f += aug;
     91                             i = edge[pre[i]^1].v;
     92                         }
     93                         aug = INF;
     94                     }
     95                     break;
     96                 }
     97                 p = edge[p].next;
     98             }
     99             if (flag) continue; //若发现可行弧则继续,否则更新标号
    100             int min = n - 1;
    101             p = pointer[i];
    102             while (p != 0) {
    103                 if ((edge[p].f > 0) && (dis[edge[p].v] < min)) {
    104                     di[i] = p; //不要忘了重置当前弧
    105                     min = dis[edge[p].v];
    106                 }
    107                 p = edge[p].next;
    108             }
    109             --vh[dis[i]];
    110             if (vh[dis[i]] == 0) break; //更新vh数组,若发现距离断层,则算法结束(GAP优化)
    111             dis[i] = min + 1;
    112             ++vh[dis[i]];
    113             if (i != s) {//退栈过程
    114                 i = edge[pre[i]^1].v;
    115                 aug = his[i];
    116             }
    117         }
    118         //输出答案
    119         printf("%d\n", flow);
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    字符编码、文件处理
    列表、字典、元祖、集合
    数字类型、字符串、列表
    学习python的第一天作业
    python基础day2-函数基础2,2019-6-25
    python基础day2-函数基础,2019-6-25
    python基础day2-文件处理,2019-6-25
    python基础day2-流程控制,2019-6-25
    python基础day2-字典类型已内置方法,2019-6-25
    python基础day2-可变类型与不可变类型,2019-6-25
  • 原文地址:https://www.cnblogs.com/yejinru/p/2687633.html
Copyright © 2011-2022 走看看