zoukankan      html  css  js  c++  java
  • bzoj3876

    有上下界的费用流

    建图:每条边连接两个节点,边的费用为花费时间,下界为1,上界正无穷,源点为1,所有点连向1,下界0,上界正无穷,表示随时可以返回,于是我们想求一个最小费用可行流

    具体做法是先建立超级源汇,对于每条有上下界的边(u,v),u->t,流量为u的入度,费用为0,s->v,流量为下界1,费用为(u,v)费用,u->v连边,流量inf,花费为(u,v)的花费,这样强迫流量流入流出,流满了下界

    其他边和之前一样连

    u->t的目的是让流入u的流量至少流过到v的边的下界,这样不会让流到u的流量小于下界,s->v的边的目的是强制流入v点至少下界的流量,花费为原来边的花费,这样保证了对于一条边(u,v),流入u的流量不少于下界,从v流出的流量至少为下界,且花费为(u,v)的花费。保证对于点u,流入u的流量至少为所有u的出边的下界之和,这样流入u,也就是流入u出边的下界可以被满足,然后点v满足了到v边下界的流量肯定能流入v,且花费分别为所有流入v的边

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 10010, inf = 1 << 29;
    struct edge {
        int nxt, to, f, c;
    } e[N << 2];
    int n, cnt = 1, source, sink;
    int head[N], d[N], pree[N], prev[N], vis[N];
    inline void link(int u, int v, int f, int 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, int f, int c)
    {
        link(u, v, f, c);
        link(v, u, 0, -c);
    }
    bool spfa()
    {
        queue<int> q;
        memset(d, -1, sizeof(d));
        q.push(source);
        d[source] = 0;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && (d[e[i].to] > d[u] + e[i].c || d[e[i].to] == -1))
            {
                d[e[i].to] = d[u] + e[i].c;
                pree[e[i].to] = i;
                prev[e[i].to] = u;
                if(vis[e[i].to] == 0)
                {
                    vis[e[i].to] = 1;
                    q.push(e[i].to);
                }
            } 
        }
        return d[sink] != -1;
    }
    int Edmonds_Karp()
    {
        int ret = 0;
        while(spfa())
        {
            int now = sink, delta = inf;
            while(now != source)
            {
                delta = min(delta, e[pree[now]].f);
                now = prev[now];
            }
            now = sink;
            while(now != source)
            {
                e[pree[now]].f -= delta;
                e[pree[now] ^ 1].f += delta;
                now = prev[now];
            }
            ret += d[sink] * delta;
        }
        return ret;
    }
    int main()
    {
        scanf("%d", &n);
        sink = n + 1;
        for(int i = 1; i <= n; ++i)
        {
            int m, b, t;
            scanf("%d", &m);
            insert(i, sink, m, 0);
            while(m--)
            {
                scanf("%d%d", &b, &t);
                insert(source, b, 1, t);
                insert(i, b, inf, t);
            }
            if(i != 1) insert(i, 1, inf, 0);    
        }
        printf("%d
    ", Edmonds_Karp());
        return 0;
    }
    View Code
  • 相关阅读:
    mysql 往表中insert的时候如何让主键id按当前表的最大值自动增长?
    visual studio 2013 win7安装笔记
    mysql奇葩之旅
    java JVM常见的四大异常及处理方案
    DDR3_旧版(2):初始化
    DDR3_旧版(1):IP核调取
    【转】AXI_Lite 总线详解
    ZYNQ笔记(7):AXI从口自定义IP封装
    ZYNQ笔记(6):普通自定义IP封装实现PL精准定时中断
    ZYNQ笔记(5):软中断实现核间通信
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7348725.html
Copyright © 2011-2022 走看看