zoukankan      html  css  js  c++  java
  • [bzoj2055] 80人环游世界

    Description

    想必大家都看过成龙大哥的《 (80) 天环游世界》,里面的紧张刺激的打斗场面一定给你留下了深刻的印象。现在就有这么

    一个 (80) 人的团伙,也想来一次环游世界。

    他们打算兵分多路,游遍每一个国家。

    因为他们主要分布在东方,所以他们只朝西方进军。设从东方到西方的每一个国家的编号依次为 (1cdots N) 。假若第i个人的游历路线为 (P_1,P_2cdots P_k(0le kle N)),则 (P_1<P_2<cdots <P_k)

    众所周知,中国相当美丽,这样在环游世界时就有很多人经过中国。我们用一个正整数 (V_i) 来描述一个国家的吸引程度,Vi值越大表示该国家越有吸引力,同时也表示有且仅有 (V_i) 个人会经过那一个国家。

    为了节省时间,他们打算通过坐飞机来完成环游世界的任务。同时为了省钱,他们希望总的机票费最小。

    明天就要出发了,可是有些人临阵脱逃,最终只剩下了 (M) 个人去环游世界。他们想知道最少的总费用,你能告诉他们吗?

    Input

    第一行两个正整数 (N,M)

    第二行有 (N) 个不大于 (M) 正整数,分别表示 (V_1,V_2cdots V_N)

    接下来有 (N-1) 行。第 (i) 行有 (N -i) 个整数,该行的第 (j) 个数表示从第 (i) 个国家到第 (i+j) 个国家的机票费(如果该值等于 (-1) 则表示这两个国家间没有通航)。

    Output

    在第一行输出最少的总费用。

    Sample Input

    6 3
    2 1 3 1 2 1
    2 6 8 5 0
    8 2 4 1
    6 1 0
    4 -1
    4
    

    Sample Output

    27
    

    HINT

    (1le N le 100,1le M le 79)

    Solution




    这大概就是题面钦定数据范围吧...

    这是一道上下界费用流。

    将国家 (x) 拆成入点 (x_1) ,出点 (x_2) ,同时建源点 (S) ,汇点 (T) ,第二源点 (SS)

    首先 $$<S, SS>:capacity=m,cost=0$$

    对于国家 (x) $$<SS,x_1>:capacity=INF,cost = 0$$ $$<x_2,T>:capacity=INF,cost=0$$ $$<x_1,x_2>:capacity=[V, V],cost=0$$

    如果 (x)(y) 有航线,则 $$<x_2,y_1>:capacity=INF,cost=W$$

    然后跑一个上下界费用流即可。具体做法是先把每条边的 (lw) 乘上 (cost) 加到答案里(当然本题不需要),再跑一个普通的费用流。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 1001
    #define INF 2000000000
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define ll long long
    
    inline int read() {
    	int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
    	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
    }
    
    int n, m, SS, SSS, TT;
    int du[N];
    
    int S, T, flow, cost;
    struct edge { int u, v, c, w, next; }e[20001];
    int head[N], tot = 1;
    int dis[N], pre[N];
    queue<int> q;
    bool inq[N];
    inline void insert(int u, int v, int c, int w) { e[++tot].u = u, e[tot].v = v, e[tot].c = c, e[tot].w = w, e[tot].next = head[u], head[u] = tot; }
    inline void add(int u, int v, int c, int w) { insert(u, v, c, w), insert(v, u, 0, -w); }
    inline bool spfa() {
    	rep(i, S, T) dis[i] = INF; dis[S] = 0; q.push(S);
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); inq[u] = 0;
    		for (int i = head[u], v, w; i; i = e[i].next) if (e[i].c > 0 && dis[v = e[i].v] > dis[u] + (w = e[i].w)) {
    			dis[v] = dis[u] + w, pre[v] = i;
    			if (!inq[v]) q.push(v); inq[v] = 1;
    		}
    	}
    	return dis[T] != INF;
    }
    inline void mcf() {
    	int d = INF;
    	for (int i = T; (i ^ S); i = e[pre[i]].u) d = min(d, e[pre[i]].c);
    	flow += d;
    	for (int i = T; (i ^ S); i = e[pre[i]].u) e[pre[i]].c -= d, e[pre[i] ^ 1].c += d, cost += d * e[pre[i]].w;
    }
    
    int main() {
    	cin >> n >> m; SSS = 2 * n + 1, SS = SSS + 1, TT = SS + 1, T = TT + 1;
    	rep(i, 1, n) {
    		add(SSS, i, INF, 0), add(i + n, TT, INF, 0);
    		int V = read(); add(i, i + n, 0, 0);
    		du[i] -= V, du[i + n] += V;
    	}
    	add(SS, SSS, m, 0);
    	rep(i, 1, n) rep(j, i + 1, n) { int V = read(); if(V != -1) add(i + n, j, INF, V); }
    	add(TT, SS, INF, 0);
    	rep(i, 1, TT) if (du[i] > 0) add(S, i, du[i], 0); else add(i, T, -du[i], 0);
    	while (spfa()) mcf(); cout << cost;
    	return 0;
    }
    
  • 相关阅读:
    致我的2018 你好2019
    第十四分块(前体)(二次离线莫队)
    [Ynoi2019模拟赛]Yuno loves sqrt technology II(二次离线莫队)
    [Ynoi2015]此时此刻的光辉(莫队)
    python+selenium+Firefox+pycharm版本匹配
    IntelliJ IDEA 配置Maven
    Jmeter如何监控服务器性能
    fiddler工具
    关于Python安装官方whl包和tar.gz包的方法详解
    浅析Web Services
  • 原文地址:https://www.cnblogs.com/aziint/p/8443433.html
Copyright © 2011-2022 走看看