题目地址:P4553 80人环游世界

上下界网络流

无源汇上下界可行流

给定 \(n\) 个点, \(m\) 条边的网络,求一个可行解,使得边 \((u,v)\) 的流量介于 \([B(u,v),C(u,v)]\) 之间,并且整个网络满足流量守恒。

如果把 \(C-B\) 作为容量上界, \(0\) 作为容量下界,就是一般的网络流模型。

然而求出的实际流量为 \(f(u,v)+B(u,v)\) ,不一定满足流量守恒,需要调整。

设 \(inB[u]=\sum B(i,u)\) , \(outB[u]=\sum B(u,i)\) , \(d[u]=inB[u]-outB[u]\) 。

新建源汇, \(S\) 向 \(d>0\) 的点连边, \(d<0\) 的点向 \(T\) 连边,容量为相应的 \(d\) 。

在该网络上求最大流,则每条边的流量 \(+\) 下界就是原网络的一个可行流。

具体实现时,可省略 \(inB,outB\) 数组,直接在 \(d\) 数组上修改。

有源汇上下界可行流

从 \(T\) 到 \(S\) 连一条下界为 \(0\) ,上界为 \(+inf\) 的边,把汇流入的流量转移给源流出的流量,转化为无源汇的网络,然后求解无源汇上下界可行流

有源汇上下界最小费用可行流

类似有源汇上下界可行流,求最大流改为求最小费用最大流。

每个国家拆成两个点(入点 \(i\) 和出点 \(i+n\)),建立源 \(s\) 汇 \(t\) 附加源 \(s\_\) 。

连边:

  1. \((s,s\_,m,m,0)\) ;
  2. \((s\_,i,0,m,0)\) ;
  3. \((i+n,t,0,m,0)\) ;
  4. \((i,i+n,V[i],V[i],0)\) ;
  5. 若 \(i,j\) 两个国家通航,连边 \((i+n,j,0,m,Cost_{i,j})\) 。

对网络 \(s-t\) 求有源汇上下界最小费用可行流

#include <bits/stdc++.h>
using namespace std;
const int N = 206, M = 1e5 + 6, inf = 0x3f3f3f3f;
int n, m, S, T, s, s_, t, d[N], now[N], pre[N], ans;
int Head[N], Edge[M], Leng[M], Cost[M], Next[M], tot = 1;
bitset<N> v;

inline void add(int x, int y, int z, int w) {
    Edge[++tot] = y;
    Leng[tot] = z;
    Cost[tot] = w;
    Next[tot] = Head[x];
    Head[x] = tot;
    Edge[++tot] = x;
    Leng[tot] = 0;
    Cost[tot] = -w;
    Next[tot] = Head[y];
    Head[y] = tot;
}

inline void ins(int x, int y, int l, int r, int w) {
    add(x, y, r - l, w);
    d[x] -= l;
    d[y] += l;
}

inline bool spfa() {
    v.reset();
    memset(d, 0x3f, sizeof(d));
    queue<int> q;
    q.push(S);
    v[S] = 1;
    d[S] = 0;
    now[S] = m;
    while (q.size()) {
        int x = q.front();
        q.pop();
        v[x] = 0;
        for (int i = Head[x]; i; i = Next[i]) {
            int y = Edge[i], z = Leng[i], w = Cost[i];
            if (!z || d[y] <= d[x] + w) continue;
            d[y] = d[x] + w;
            now[y] = min(now[x], z);
            pre[y] = i;
            if (!v[y]) {
                q.push(y);
                v[y] = 1;
            }
        }
    }
    return d[T] != inf;
}

inline void upd() {
    ans += d[T] * now[T];
    int x = T;
    while (x != S) {
        int i = pre[x];
        Leng[i] -= now[T];
        Leng[i^1] += now[T];
        x = Edge[i^1];
    }
}

int main() {
    cin >> n >> m;
    s = n * 2 + 1, s_ = s + 1, t = s_ + 1;
    S = t + 1, T = S + 1;
    ins(s, s_, m, m, 0);
    for (int i = 1; i <= n; i++) {
        ins(s_, i, 0, m, 0);
        ins(i + n, t, 0, m, 0);
        int x;
        scanf("%d", &x);
        ins(i, i + n, x, x, 0);
    }
    for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++) {
            int x;
            scanf("%d", &x);
            if (~x) ins(i + n, j, 0, m, x);
        }
//  ins(t, s, 0, m, 0);
    for (int i = 1; i <= t; i++) {
        if (d[i] > 0) add(S, i, d[i], 0);
        else if (d[i] < 0) add(i, T, -d[i], 0);
    }
    while (spfa()) upd();
    cout << ans << endl;
    return 0;
}

注意:代码中注释的那一条语句加不加都可以AC,具体原因有待研究(讨论

P4553 80人环游世界的更多相关文章

  1. P4553 80人环游世界(上下界费用流)

    P4553 80人环游世界 emm......先从上下界网络流(转)开始 再到现在的上下界费用流 因为有上下界,我们需要记下每个点的流量差$ex[i]$,用于调整 $ins(x,y,l,r,v)=li ...

  2. 洛谷P4553 80人环游世界

    题目描述 https://www.luogu.org/problemnew/show/P4553 题解 思路比较显然,把图建出来,一个国家拆成两个点,中间设置上下界,然后跑费用流. 我把源那边的流量也 ...

  3. Luogu P4553 80人环游世界

    link 题目大意 自东向西有 \(n\) 个国家.有 \(m\) 个人,他们可以选择 \(n\) 个国家中任意一个开始,任意一个结束,但路线必须自东向西,且第 \(i\) 个国家必须恰好经过 \(v ...

  4. 【BZOJ-2055】80人环游世界 上下界费用流 (无源无汇最小费用最大流)

    2055: 80人环游世界 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 321  Solved: 201[Submit][Status][Discus ...

  5. BZOJ2055: 80人环游世界

    题解: 总算A掉了,各种蛋疼... int main() { freopen("input.txt","r",stdin); freopen("out ...

  6. BZOJ 2055: 80人环游世界 [上下界费用流]

    2055: 80人环游世界 题意:n个点带权图,选出m条路径,每个点经过val[i]次,求最小花费 建图比较简单 s拆点限制流量m 一个点拆成两个,限制流量val[i],需要用上下界 图中有边的连边, ...

  7. [BZOJ2055]80人环游世界 有上下界最小费用最大流

    2055: 80人环游世界 Time Limit: 10 Sec  Memory Limit: 64 MB Description     想必大家都看过成龙大哥的<80天环游世界>,里面 ...

  8. bzoj 2055: 80人环游世界 -- 上下界网络流

    2055: 80人环游世界 Time Limit: 10 Sec  Memory Limit: 64 MB Description     想必大家都看过成龙大哥的<80天环游世界>,里面 ...

  9. 【BZOJ】2055 80人环游世界

    [算法]有源汇上下界最小费用可行流 [题解]上下界 因为上下界相同,所以无所谓最小流了,可行流(初始流+附加流)就是答案了. 记得源点向新建节点连一条容量为m(人)的边. bzoj 2055 80人环 ...

随机推荐

  1. mysql 将一张表的数据更新到另外一张表中

    update 更新表 set 字段 = (select 参考数据 from 参考表 where  参考表.id = 更新表.id); update table_2 m  set m.column = ...

  2. 【clustering】之K-means && K-medoids

    k-means k-medoids 一.clustering 中的 loss function 关于聚类的性能评价标准 参考博客 可以为外部指标和内部指标,其中外部指标是指 聚类结果与某个 “参考模型 ...

  3. SQL语法基础之高级应用

    SQL语法基础之高级应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.存储过程与函数 1>.CREATE PROCEDURE 用来创建存储过程 mysql> ? ...

  4. MySQL中的主键,外键有什么作用详解

    MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...

  5. PHP 连接 Memcached 服务

    1.需要安装php的Memcached扩展,具体安装步骤不做介绍了. 2.php连接memcached的mem.php 文件 <?php $memcache = new Memcached; $ ...

  6. Java Web之表单重复提交问题

    上篇文章讲了验证码的制作,提及到了一个问题,就是表单重复提交的问题,可能在上次那个验证码中感觉不是那么的重要 现在我新写一个例子,转钱.通过这个例子你就知道表单重复提交有多恐怖了. 先来简单的介绍一下 ...

  7. Java中Sax解析XML

    SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式:这种解析方法速度快.占用内存少,但是它需要应用程序自己处理 ...

  8. 使用git遇到的一些问题

    上传github时忽略.DS_Store方法 这个文件在mac中是管理文件夹的位置之类的信息,所以并没有必要上传到git中,这个时候就需要用git.gitignore文件来忽略此类文件. 在默认情况下 ...

  9. ArcGis Go to XY功能代码C#

    IPoint point = new PointClass(); point.PutCoords(x,y); IEnvelope pEnvelope= this.m_hookHelper.Active ...

  10. NLP里面的一些基本概念

    1,corpus 语料库 a computer-readable collection of text or speech 2,utterance 发音 比如下面一句话:I do uh main- m ...