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

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2055

    【题解】

    跟上一题(支线剧情)很像,与上题不同是这题看作求“最大流”(我们限制过流量了),上一题是求“可行流”无源汇的做法。

    我们考虑先建出带有上下界的网络流:

    S1->S2 [m,m] cost = 0

    out(i)->in(j) [0, inf] cost = p[i][j]

    in(i)->out(i) [vi, vi] cost = 0;

    out(i)->T [0, inf] cost = 0

    注意p[i][j]=-1不要建边

    那么这样过后,直接按照通常转成非下界限制的费用流做就行了

    因为这题有源汇,所以不需要提前算答案

    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 210;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, S, T;
    int p[N][N], V[N], d[N];
    
    int head[M], nxt[M], to[M], flow[M], w[M], tot=1;
    inline void add(int u, int v, int fl, int _w) {
        ++tot; nxt[tot] = head[u]; head[u] = tot;
        to[tot] = v; flow[tot] = fl; w[tot] = _w;
    }
    inline void adde(int u, int v, int fl, int _w) {
        add(u, v, fl, _w);
        add(v, u, 0, -_w);
    }
    
    namespace MCF {
        queue<int> q;
        int dis[M], pre[M];
        bool vis[M];
        inline bool spfa() {
            while(!q.empty()) q.pop();
            for (int i=1; i<=n+n+5; ++i) vis[i] = 0, dis[i] = 1e9, pre[i] = 0;
            q.push(S); vis[S] = 1; dis[S] = 0;
            while(!q.empty()) {
                int top = q.front(); q.pop(); vis[top] = 0;
                for (int i=head[top]; i; i=nxt[i]) {
                    if(flow[i] && dis[to[i]] > dis[top] + w[i]) {
                        dis[to[i]] = dis[top] + w[i];
                        pre[to[i]] = i;
                        if(!vis[to[i]]) {
                            vis[to[i]] = 1;
                            q.push(to[i]);
                        }
                    }
                }
            }
            return dis[T] != 1e9;
        }
        inline int mcf() {
            int fl = 1e9, ans = 0;
            for (int i=pre[T]; i; i=pre[to[i^1]])
                fl = min(fl, flow[i]);
            for (int i=pre[T]; i; i=pre[to[i^1]]) {
                flow[i] -= fl;
                flow[i^1] += fl;
                ans += fl * w[i];
            }
            return ans;
        }
        inline int main() {
            int ret = 0;
            while(spfa()) ret += mcf();
            return ret;
        }
    }
    
    inline void ADD(int u, int v, int fll, int flr, int _w) {
        adde(u, v, flr-fll, _w);
        d[v] += fll; d[u] -= fll;
    }
    
    int main() {
        cin >> n >> m;
        for (int i=1; i<=n; ++i) scanf("%d", &V[i]);
        for (int i=1; i<=n; ++i)
            for (int j=i+1; j<=n; ++j) scanf("%d", &p[i][j]);
        
        int S1 = n+n+1, S2 = n+n+2, T0 = n+n+3;
        
        for (int i=1; i<=n; ++i) ADD(i, i+n, V[i], V[i], 0);
        for (int i=1; i<=n; ++i)
            for (int j=i+1; j<=n; ++j)
                if(p[i][j] != -1) ADD(i+n, j, 0, 1e9, p[i][j]);
        
        ADD(S1, S2, m, m, 0);
        for (int i=1; i<=n; ++i) ADD(S2, i, 0, 1e9, 0);
        for (int i=1; i<=n; ++i) ADD(i+n, T0, 0, 1e9, 0);
        
        S = n+n+4, T = n+n+5;
        for (int i=1; i<=n+n+3; ++i) {
            if(d[i] > 0) adde(S, i, d[i], 0);
            if(d[i] < 0) adde(i, T, -d[i], 0);
        }
        
        cout << MCF::main() << endl;
        
        return 0;
    }
    View Code
  • 相关阅读:
    没有找到MSVCR100.dll解决方法
    Python用subprocess的Popen来调用系统命令
    我是怎样成长为系统架构师的
    【java读书笔记】——Collection集合之六大接口(Collection、Set、List、Map、Iterator和Comparable)
    SQLite的SQL语法
    MVC中使用AuthorizeAttribute做身份验证操作
    windows知识点
    java实现第五届蓝桥杯斐波那契
    java实现第五届蓝桥杯绳圈
    java实现第五届蓝桥杯绳圈
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2055.html
Copyright © 2011-2022 走看看