zoukankan      html  css  js  c++  java
  • 网络流

        网络流是一种神奇的东西,它的问题大致为:你在S号城市拥有很多物资,现在你要把它们运到城市T,除此之外还有很多其他城市,有些城市间有道路,有些没有,且每条道路都有所运物资的最大量。你可以先把一些物资从S直接运向T(必须S到T有道路且运的物资总量小于这条道路的最大量),再把另一些运往A,再从A运向T(须S到A,A到T有道路,且运送物资量都小于这两条道路的最大量)
        最大流
        顾名思义就是求从S到T最多运多少物资,这个问题理解了也不难。
        不断重复以下步骤:
        1.维护一个队列,用类似SPFA的方法求出从S到每一个城市运送的可能的物资数(不为0,也不一定最大),并记录其父节点;
        2.判断是否有物资运到T城市,如果没有就退出循环;
        3.如果有物资运到T城市,就把当前记录的运到T的物资累加入总计,并把本次记录的从S到T的路径上每一条道路的最大量减去当前记录的值(代表吧这些物资运过去了)。
        这个方法叫增广路。
        代码如下(云神教的):

    int sap(int p,int f){
        if (p==ty) return f;
        int h=0;
        for (int i=d[p];i;i=bi[i].ne)
        if ((bi[i].l)&&(c[bi[i].y]+1==c[p])){
            int q=sap(bi[i].y,min(f-h,bi[i].l));
            //printf("%d %d
    ",bi[i].y,q);
            h+=q;
            bi[i].l-=q;bi[bi[i].pa].l+=q;d[p]=i;//当前弧优化
            if (h==f) return f;
        }
        if (c[sy]>=no) return h;//分层
        g[c[p]]--;
        if (!(g[c[p]])) c[sy]=no;
        c[p]++;
        g[c[p]]++;d[p]=la[p];
        return h;
    }

        最小割
        这是指摧毁掉一些道路,使得不可能有物资运从S到T,且代价最小。
        同样是增广路算法,最后一个循环做完后有标记的点和未标记的点分为两个点集,删去连接两个点集的点,即为最小割。
        费用流
        在最大流的基础上,每条道路都有一定费用,要求在物资最多的前提下费用最小。
        只须在增广路中加一点判断使费用最小就行了。

      完……

  • 相关阅读:
    洛谷 P1236 算24点
    洛谷 P1483 序列变换
    洛谷 P2071 座位安排 seat.cpp/c/pas
    洛谷 P3079 [USACO13MAR]农场的画Farm Painting
    洛谷 P3912 素数个数
    洛谷 P1617 爱与愁的一千个伤心的理由
    洛谷 P1894 [USACO4.2]完美的牛栏The Perfect Stall
    hdu_5908_Abelian Period(暴力)
    hdu_4283_You Are the One(区间DP)
    hdu_5903_Square Distance(dp)
  • 原文地址:https://www.cnblogs.com/Enceladus/p/4979135.html
Copyright © 2011-2022 走看看