• 志愿者招募 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;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    (一)Sturts2概述
    day18,常用的模块,os,sys...等
    day17,模块的导入
    day16
    day15
    day14
    day13
    day12
    day11
    day10
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9955187.html
Copyright © 2020-2023  润新知