@bzoj - 1061 @ [Noi2008] Volunteer Recruitment


@description@

  After the successful Olympic bid, boob through unremitting efforts, has finally become director of BOCOG subsidiary HR department. Bubu took office just ran into a problem: the recruitment of a number of short-term volunteers for the upcoming launch of the new Olympic project. After estimating that the project requires N days to complete, with the first day at least i Ai individual. Bubu by understanding that a total of M class volunteers can be recruited. Wherein the i-type Si from the first day to work on Day Ti, Ci recruitment costs per person. New broom sweeps clean, well done to their jobs, boob to exhaust less cost of recruiting enough volunteers, but this is not his specialty! So Bubu found you, I hope you help him design an optimal recruitment programs.

Input
  The first line contains two integers N, M, indicating the type and number of days to complete the project can recruit volunteers. The next line contains N non-negative integers, it represents the required minimum number of volunteers per day. The next M rows each line contains three integers Si, Ti, Ci, meanings as described above. For convenience, we can say that the number of each type are an infinite number of volunteers.

Output
  only contains an integer that represents the total cost of the optimal solution of your design.

Sample Input
3 3
2 3 4
1 2 2
2 3 5
3 3 2
Sample Output
14

The HINT
. 1 ≤ N ≤ M ≤ ≤ 1000,1 10000, the title of the other data involved does not exceed 2 ^ 31-1.

@solution@

Linear programming model can be heard, but I will not. . .
But at least it can be seen clearly This is a relatively linear programming, see the data range finding simplex trouble, then associate to the network stream.

Consider the question set Ai said at least personal, in fact, may correspond to the upper and lower bounds of the lower bound of network flow.
0 No new point for each 1 <= i <= n, even i-1 -> i which represents the number of edges on day i volunteers recruited. This side of the lower bound of Ai, the upper bound inf, cost is zero.

Topic that will be used the cost of Si to Ti Ci these days plus a corresponding edge flow. . .
Consider using flow balance thought, Si corresponding to the days of these edges form a chain Ti Si - 1 -> Si -> ... -> Ti. If even edge Ti -> Si - 1, can be formed circulation flow balance constraints satisfied.
So, we upper and lower bounds of the original flow in the network even Ti -> Si - 1, 0 for the lower bound, the upper bound inf, cost Ci.

In this sector ran up and down the stream network with the least possible passive bus can be.

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 1000;
const int MAXM = 10000;
const int MAXV = 1000;
const int MAXE = 2*MAXM + 5*MAXV + 5;
const int INF = (1<<30);
struct FlowGraph{
    struct edge{
        int to, cap, flow, cost;
        edge *nxt, *rev;
    }edges[MAXE + 5], *adj[MAXV + 5], *cur[MAXV + 5], *ecnt;
    FlowGraph() {ecnt = &edges[0];}
    int s, t;
    void addedge(int u, int v, int c, int w) {
        edge *p = (++ecnt), *q = (++ecnt);
        p->to = v, p->cap = c, p->flow = 0, p->cost = w;
        p->nxt = adj[u], adj[u] = p;
        q->to = u, q->cap = 0, q->flow = 0, q->cost = -w;
        q->nxt = adj[v], adj[v] = q;
        p->rev = q, q->rev = p;
//      printf("! %d %d %d %d\n", u, v, c, w);
    }
    int f[MAXV + 5], hp[MAXV + 5];
    void update(int x, int k) {
        f[x] = k;
        while( x ) {
            hp[x] = x;
            if( (x<<1) <= t && f[hp[x<<1]] < f[hp[x]] )
                hp[x] = hp[x<<1];
            if( (x<<1|1) <= t && f[hp[x<<1|1]] < f[hp[x]] )
                hp[x] = hp[x<<1|1];
            x >>= 1;
        }
    }
    int d[MAXV + 5], h[MAXV + 5];
    bool relabel() {
        for(int i=1;i<=t;i++)
            h[i] += d[i], d[i] = f[i] = INF, hp[i] = i, cur[i] = adj[i];
        update(s, d[s] = 0);
        while( f[hp[1]] != INF ) {
            int x = hp[1]; update(x, INF);
            for(edge *p=adj[x];p;p=p->nxt) {
                int w = p->cost + h[x] - h[p->to];
                if( p->cap > p->flow && d[x] + w < d[p->to] )
                    update(p->to, d[p->to] = d[x] + w);
            }
        }
        return !(d[t] == INF);
    }
    bool vis[MAXV + 5];
    int aug(int x, int tot) {
        if( x == t ) return tot;
        int sum = 0; vis[x] = true;
        for(edge *&p=cur[x];p;p=p->nxt) {
            int w = p->cost + h[x] - h[p->to];
            if( !vis[p->to] && p->cap > p->flow && d[x] + w == d[p->to] ) {
                int del = aug(p->to, min(tot - sum, p->cap - p->flow));
                p->flow += del, p->rev->flow -= del, sum += del;
                if( sum == tot ) break;
            }
        }
        vis[x] = false;
        return sum;
    }
    int min_cost_max_flow(int _s, int _t) {
        s = _s, t = _t; int cost = 0;
        while( relabel() )
            cost += (h[t] + d[t])*aug(s, INF);
        return cost;
    }
}G;
int A[MAXN + 5];
int N, M, s, t;
int main() {
    scanf("%d%d", &N, &M), s = N + 2, t = N + 3;
    for(int i=1;i<=N;i++)
        scanf("%d", &A[i]);
    for(int i=0;i<=N;i++) {
        if( A[i] < A[i + 1] )
            G.addedge(i + 1, t, A[i + 1] - A[i], 0);
        else if( A[i] > A[i + 1] )
            G.addedge(s, i + 1, A[i] - A[i + 1], 0);
    }
    for(int i=0;i<N;i++)
        G.addedge(i + 1, i + 2, INF, 0);
    for(int i=1;i<=M;i++) {
        int S, T, C; scanf("%d%d%d", &S, &T, &C);
        G.addedge(T + 1, S, INF, C);
    }
    printf("%d\n", G.min_cost_max_flow(s, t));
}

@details@

In fact, Figure and linear programming modeling last built out of the same.

In addition, to achieve personal habits of reason codes, and number all points are moved back one (that is, the original number 1 becomes 0:00 o'clock, and so on).

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11416749.html
Recommended