zoukankan      html  css  js  c++  java
  • 志愿者招募 HYSBZ

    转自神犇:https://www.cnblogs.com/jianglangcaijin/p/3799759.html

    题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最 优的招募方案。

    思路:

    这个一个类影响一个区间,所以并不能像HDU - 3572 一样 按时间拆点

    一系列每个变量等式左右各只出现一次的等式,然后用流量平衡建图即可。

    所以列出公式求解

    例如一共需要4天,四天需要的人数依次是4,2,5,3。有5类志愿者,如下表所示:

    设雇佣第i类志愿者的人数为X[i],每个志愿者的费用为V[i],第j天雇佣的人数为P[j],则每天的雇佣人数应满足一个不等式,如上表所述,可以列出

    P[1]=X[1]+X[2]>=4

    P[2]=X[1]+X[3]>=2

    P[3]=X[3]+X[4]+X[5]>=5

    P[4]=X[5]>=3

    对于第i个不等式,添加辅助变量Y[i](Y[i]>=0),可以使其变为等式

    P[1]=X[1]+X[2]-Y[1]=4

    P[2]=X[1]+X[3]-Y[2]=2

    P[3]=X[3]+X[4]+X[5]-Y[3]=5

    P[4]=X[5]-Y[4]=3

    在上述四个等式上下添加P[0]=0,P[5]=0,每次用下边的式子减去上边的式子,得出

    ① P[1]-P[0]=X[1]+X[2]-Y[1]=4

    ② P[2]-P[1]=X[3]-X[2]-Y[2]+Y[1]=-2

    ③ P[3]-P[2]=X[4]+X[5]-X[1]-Y[3]+Y[2]=3

    ④ P[4]-P[3]=-X[3]-X[4]+Y[3]-Y[4]=-2

    ⑤ P[5]-P[4]=-X[5]+Y[4]=-3

    观察发现,每个变量都在两个式子中出现了,而且一次为正,一次为负.所有等式右边和为0.我们将最后的五个等式进一步变形,得出以下结果

    ① -X[1]-X[2]+Y[1]+4=0

    ② -X[3]+X[2]+Y[2]-Y[1]-2=0

    ③ -X[4]-X[5]+X[1]+Y[3]-Y[2]+3=0

    ④ X[3]+X[4]-Y[3]+Y[4]-2=0

    ⑤ X[5]-Y[4]-3=0

    可 以发现,每个等式左边都是几个变量和一个常数相加减,右边都为0,恰好就像网络流中除了源点和汇点的顶点都满足流量平衡。每个正的变量相当于流入该顶点的 流量,负的变量相当于流出该顶点的流量,而正常数可以看作来自附加源点的流量,负的常数是流向附加汇点的流量。因此可以据此构造网络,求出从附加源到附加 汇的网络最大流,即可满足所有等式。而我们还要求费用最小,所以要在X变量相对应的边上加上权值,然后求最小费用最大流。

    接下来,根据上面五个等式构图。

    (1)每个等式为图中一个顶点,添加源点S和汇点T。

    (2)如果一个等式中的数字为非负整数c,从源点S向该等式对应的顶点连接一条容量为c,权值为0的有向边;如果为负整数-c,从该等式对应的顶点向汇点T连接一条容量为c,权值为0的有向边。

    (3)如果一个变量X[i]在第j个等式中出现为-X[i],在第k个等式中出现为+X[i],从顶点j向顶点k连接一条容量为INF,权值为V[i]的有向边。

    (4)如果一个变量Y[i]在第j个等式中出现为-Y[i],在第k个等式中出现为+Y[i],从顶点j向顶点k连接一条容量为INF,权值为0的有向边。

    构图以后,求从源点S到汇点T的最小费用最大流,费用值就是结果。

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    #include <cstring>
    #include <map>
    #include <cctype>
    #include <set>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <bitset>
    #define rap(i, a, n) for(int i=a; i<=n; i++)
    #define rep(i, a, n) for(int i=a; i<n; i++)
    #define lap(i, a, n) for(int i=n; i>=a; i--)
    #define lep(i, a, n) for(int i=n; i>a; i--)
    #define rd(a) scanf("%d", &a)
    #define rlld(a) scanf("%lld", &a)
    #define rc(a) scanf("%c", &a)
    #define rs(a) scanf("%s", a)
    #define rb(a) scanf("%lf", &a)
    #define rf(a) scanf("%f", &a)
    #define pd(a) printf("%d
    ", a)
    #define plld(a) printf("%lld
    ", a)
    #define pc(a) printf("%c
    ", a)
    #define ps(a) printf("%s
    ", a)
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define _  ios_base::sync_with_stdio(0),cin.tie(0)
    //freopen("1.txt", "r", stdin);
    using namespace std;
    const int maxn = 1e5 + 10, INF = 0x7fffffff, LL_INF = 0x7fffffffffffffff;
    int n, m, s, t;
    int head[maxn], d[maxn], vis[maxn], nex[maxn], f[maxn], p[maxn], cnt;
    int xu[maxn], flow, value;
    
    struct node
    {
        int u, v, w, c;
    }Node[maxn];
    
    void add_(int u, int v, int w, int c)
    {
        Node[cnt].u = u;
        Node[cnt].v = v;
        Node[cnt].w = w;
        Node[cnt].c = c;
        nex[cnt] = head[u];
        head[u] = cnt++;
    }
    
    void add(int u, int v, int w, int c)
    {
        add_(u, v, w, c);
        add_(v, u, -w, 0);
    }
    
    int spfa()
    {
        for(int i = 0; i < maxn; i ++) d[i] = INF;
        deque<int> Q;
        mem(vis, 0);
        mem(p, -1);
        Q.push_front(s);
        d[s] = 0;
        p[s] = 0, f[s] = INF;
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop_front();
            vis[u] = 0;
            for(int i = head[u];i != -1; i = nex[i])
            {
                int v = Node[i].v;
                if(Node[i].c)
                {
                    if(d[v] > d[u] + Node[i].w)
                    {
                        d[v] = d[u] + Node[i].w;
                        p[v] = i;
                        f[v] = min(f[u], Node[i].c);
                        if(!vis[v])
                        {
                          //  cout << v << endl;
                            if(Q.empty()) Q.push_front(v);
                            else
                            {
                                if(d[v] < d[Q.front()]) Q.push_front(v);
                                else Q.push_back(v);
                            }
                            vis[v] = 1;
                        }
                    }
                }
            }
        }
        if(p[t] == -1) return 0;
        flow += f[t], value += f[t] * d[t];
       // cout << value << endl;
        for(int i = t; i != s; i = Node[p[i]].u)
        {
            Node[p[i]].c -= f[t];
            Node[p[i] ^ 1].c += f[t];
        }
        return 1;
    }
    
    void max_flow()
    {
        flow = value = 0;
        while(spfa());
        pd(value);
    }
    
    void init()
    {
        mem(head, -1);
        cnt = 0;
    }
    
    int main()
    {
        init();
        int u, v, w;
        rd(n), rd(m);
        s = 0, t = n + 3;
        for(int i = 1; i <= n; i++)
        {
            rd(xu[i]);
        }
        for(int i = 1; i <= m; i++)
        {
            rd(u), rd(v), rd(w);
            add(u, v + 1, w, INF);
        }
        for(int i = 1; i <= n+1; i++)
        {
            int tmp = xu[i] - xu[i - 1];
            if(tmp > 0) add(s, i, 0, tmp);
            else add(i, t, 0, -tmp);
            if(i > 1) add(i, i - 1, 0, INF);
        }
        max_flow();
    
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9955187.html
Copyright © 2011-2022 走看看