1061 [Noi2008]ボランティア募集@ - @bzoj


@説明@

  不断の努力によって成功したオリンピック入札、豊胸手術の後、最終的にはBOCOG子会社の人事部門のディレクターとなっています。新しいオリンピックプロジェクトの今後の立ち上げのための短期ボランティアの数の動員を:ブブはちょうど問題に走ったに就任しました。プロジェクトは、少なくとも愛個々のI初日で、完了するまでにN日間が必要であることを推定した後。ブブMクラスのボランティアの合計を募集することができることを理解することによって。ここで初日からのi型SiはデイはTi、一人あたりのCI募集コスト上で動作します。新しいほうきスイープ、きれいなだけでなく自分の仕事に行って、十分なボランティアを募集するあまりコストを排出するために豊胸手術が、これは彼の専門ではありません!だから、ブブがあなたを見つけ、私はあなたが彼が最適な募集プログラムの設計を支援願っています。

入力
  の最初の行には、ボランティアを募集することができ、プロジェクトを完了するために、日の種類と数を示す、二つの整数N、Mが含まれています。次の行は、1日あたりボランティアの必要最小数を表し、nは負でない整数を含みます。次のM行はそれぞれの行は三つの整数のSi、Tiの、CI、上述したような意味を含んでいます。利便性のために、私たちはそれぞれのタイプの数は、ボランティアの数が無限であると言うことができます。

出力は
  、あなたのデザインの最適なソリューションの総コストを表す整数が含まれています。

サンプル入力
3 3
2 3 4
1 2 2
2 3 5
3 3 2
サンプル出力
14

HINT
。関与する他のデータのタイトルが2 ^ 31-1を超えない1≤N≤M≤≤1000,1 10000、。

@溶液@

リニアプログラミングモデルを聞くことができますが、私はしません。
しかし、少なくともデータがネットワークストリームに関連付け、その後、シンプレックストラブルを見つけるの範囲を参照、これは比較的線形計画法で明確に見ることができます。

質問セットAiは、実際には、少なくとも個人前記検討、ネットワークフローの下限の上限および下限に対応することができます。
0新しいポイント各1 <= iが<= N、偶数I-1 - > iはボランティア募集日のエッジの数を表し、I。あい、上限INFの下限のこの側面は、コストはゼロです。

TiのCIへのSiのコストこれらの日プラス対応するエッジの流れを使用するトピック。
>シリコン- - > 1 -鎖のTiのSiを形成するSiはこれらのエッジの日に対応する、フローバランス思想を使用することを検討して ... - >チタン。>シリコン- -もTiのエッジ場合は1を、満足循環流バランス制約を形成することができます。
そこで、ネットワーク内の元の流れさえのTiの上限と下限- >シリコン-下限、上限INF 1、0は、CIを要します。

この分野で駆け上がっおよび最小限のパッシブバスと河川ネットワークダウンすることができます。

@acceptedコード@

#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));
}

@詳細@

実際には、図および線形プログラミングモデルは、最後に同じの外に構築されました。

加えて、個人的な理由コードの習慣、および数を達成するために全ての点(つまり、元の番号1はそうで0:00時になり、)バックいずれかを移動させます。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11416749.html