zoukankan      html  css  js  c++  java
  • 713C

    费用流

    并没有想出来构图方法 我们设立源汇,其实我们关心的是相邻两个值的差值,如果差值小于0说明需要长高,那么向汇点连边差值,说明需要修改,如果差大于零,那么由源点连边差值,说明可以提供修改空间,再由源点向1和n+1连边inf,因为这两个点是可以无限修改的。然后1-2-3-n+1连双向边,费用为1,容量inf,表明修改差值。正向流是提高后面的值,反向流是降低前面的值。而且得加堆优化迪杰斯特拉,否则跑不过去了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, int> PII;
    const int N = 3010;
    const ll inf = 100000000000010;
    struct edge {
        int nxt, to;
        ll f, c;
    } e[N * 20];
    int inq[N], a[N], b[N], head[N], pree[N], pprev[N];
    ll dis[N];
    priority_queue<PII, vector<PII>, greater<PII> > q;
    int n, source, sink, cnt = 1;
    inline void link(int u, int v, ll f, ll c)
    {
        e[++cnt].nxt = head[u];
        head[u] = cnt;
        e[cnt].to = v;
        e[cnt].f = f;
        e[cnt].c = c;
    }
    inline void insert(int u, int v, ll f, ll c)
    {
        link(u, v, f, c);
        link(v, u, 0, -c);
    }
    inline bool spfa()
    {
        int l = 1, r = 0;
        for(int i = source; i <= sink; ++i)
            dis[i] = inf;
        dis[source] = 0;
        q.push(make_pair(0, source));
        while(!q.empty())
        {
            PII x = q.top();
            q.pop();
            int u = x.second;
            if(dis[u] != x.first) continue;
            for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && dis[e[i].to] > dis[u] + e[i].c)
            {
                pree[e[i].to] = i;
                pprev[e[i].to] = u;
                dis[e[i].to] = dis[u] + e[i].c;
                q.push(make_pair(dis[e[i].to], e[i].to));
            }
        }
        return dis[sink] != inf;
    }
    inline ll getflow()
    {
        int now = sink;
        ll delta = inf;
        while(now != source)
        {
            delta = min(delta, e[pree[now]].f);
            now = pprev[now];
        }
        now = sink;
        while(now != source)
        {
            e[pree[now]].f -= delta;
            e[pree[now] ^ 1].f += delta;
            now = pprev[now];
        }
        return delta * dis[sink];
    }
    inline ll mcmf()
    {
        ll ret = 0;
        while(spfa()) ret += getflow();
        return ret;
    }
    int main()
    {
        scanf("%d", &n);
        source = 0;
        sink = n + 2;
        for(int i = 1; i <= n; ++i) 
            scanf("%d", &a[i]);
        for(int i = 2; i <= n; ++i)
        {
            b[i] = a[i] - a[i - 1];
            if(b[i] > 0) insert(i, sink, b[i] - 1, 0);
            else insert(source, i, -b[i] + 1, 0);
        }
        for(int i = 1; i <= n; ++i) 
        {
            insert(i, i + 1, inf, 1);
            insert(i + 1, i, inf, 1);
        }
        insert(1, sink, inf, 0);
        insert(n + 1, sink, inf, 0);
        printf("%lld
    ", mcmf());
        return 0;
    }
    View Code
  • 相关阅读:
    Javascript在使用import 与export 区别及使用
    【repost】Python正则表达式
    js常见算法
    【repost】 JS变量重复声明以及忽略var 声明的问题及其背后的原理
    【repost】javascript callback
    【repost】js window对象属性和方法相关资料整理
    Donald Knuth
    前端知识体系
    【repost】让你一句话理解闭包(简单易懂)
    【repost】图解Javascript上下文与作用域
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7157920.html
Copyright © 2011-2022 走看看