zoukankan      html  css  js  c++  java
  • 洛谷P4009骑车加油行驶问题(分层图、最小费用最大流)

    洛谷P4009骑车加油行驶问题

    题目链接

    建一个(k+1)层的图,第0层为到加油站,第(i) ((1leq i leq k))层为走了(i)步,每个点向下一层中与它四联通的点建流量为1花费为0的边。需要注意它只要经过加油站就必须要加油,所以在1到k层中,加油站的点只能向第0层建边,不可向下一层建边

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 300100;
    const int maxm = 3000100;
    const int inf = 0x3f3f3f3f;
    typedef long long ll;
    struct edge {
        int to, next, cap, flow, cost;
    } e[maxm];
    int head[maxn], tot;
    int pre[maxn], dis[maxn];
    bool vis[maxn];
    int N;
    
    void init(int n) {
        N = n;
        tot = 1;
        memset(head, 0, sizeof(head));
    }
    
    void addedge(int u, int v, int cap, int cost) {
        e[++tot].to = v, e[tot].next = head[u], e[tot].cap = cap, e[tot].cost = cost, e[tot].flow = 0, head[u] = tot;
        e[++tot].to = u, e[tot].next = head[v], e[tot].cap = 0, e[tot].flow = 0, e[tot].cost = -cost, head[v] = tot;
    }
    
    bool spfa(int s, int t) {
        deque<int> q;
        for (int i = 0; i <= N; ++i) {
            dis[i] = inf;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push_front(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop_front();
            vis[u] = 0;
            for (int i = head[u]; i; i = e[i].next) {
                int v = e[i].to;
                if (e[i].cap > e[i].flow && dis[v] > dis[u] + e[i].cost) {
                    dis[v] = dis[u] + e[i].cost;
                    pre[v] = i;
                    if (!vis[v]) {
                        vis[v] = true;
                        if (!q.empty()) {
                            if (dis[v] < dis[q.front()]) q.push_front(v);
                            else q.push_back(v);
                        } else q.push_back(v);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    
    //return 最大流,cost为最小费用
    int mcfc(int s, int t, ll &cost) {
        cost = 0;
        int flow = 0;
        while (spfa(s, t)) {
            int minn = inf;
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                if (minn > e[i].cap - e[i].flow) {
                    minn = e[i].cap - e[i].flow;
                }
            }
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                e[i].flow += minn;
                e[i ^ 1].flow -= minn;
                cost += 1ll * e[i].cost * minn;
            }
            flow += minn;
        }
        return flow;
    }
    
    int mp[200][200];
    int n;
    
    inline int getid(int deep, int i, int j) {
        return deep * n * n + (i - 1) * n + j;
    }
    
    int main() {
    //    freopen("in.txt", "r", stdin);
        int k, A, B, C;
        scanf("%d %d %d %d %d", &n, &k, &A, &B, &C);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                scanf("%d", &mp[i][j]);
            }
        }
        int s = 0, t = getid(k + 1, 1, 1);
        init(t + 1);
        addedge(s, getid(0, 1, 1), 1, 0);
        for (int deep = 0; deep <= k; deep++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (mp[i][j] && deep) {
                        addedge(getid(deep, i, j), getid(0, i, j), 1, A);
                        continue;
                    }
                    if (deep < k) {
                        if (j + 1 <= n)
                            addedge(getid(deep, i, j), getid(deep + 1, i, j + 1), 1, 0);
                        if (i + 1 <= n)
                            addedge(getid(deep, i, j), getid(deep + 1, i + 1, j), 1, 0);
                        if (j - 1 >= 1)
                            addedge(getid(deep, i, j), getid(deep + 1, i, j - 1), 1, B);
                        if (i - 1 >= 1)
                            addedge(getid(deep, i, j), getid(deep + 1, i - 1, j), 1, B);
                    }
                    int cost;
                    if (deep == 0) continue;
                    if (mp[i][j])cost = A;
                    else cost = C + A;
                    addedge(getid(deep, i, j), getid(0, i, j), 1, cost);
                }
            }
            addedge(getid(deep, n, n), t, 1, 0);
        }
        ll ans = 0;
        mcfc(s, t, ans);
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    Springboot 报错 Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    layui时间戳转日期踩坑
    前端 传入Date 为空的解决办法
    解决springdatajpa设置默认值保存null无效的问题
    2020-04-12工作记录
    js原型链继承的傻瓜式详解
    一个关于python装饰器参数的问题
    【转】Unicode utf8等编码类型的原理
    c/c++内存泄露的检测方法
    【转】什么是动态规划?动态规划的意义是什么
  • 原文地址:https://www.cnblogs.com/albert-biu/p/11498633.html
Copyright © 2011-2022 走看看