1. 程式人生 > >[BZOJ1061][NOI2008]志願者招募 費用流

[BZOJ1061][NOI2008]志願者招募 費用流

/**************************************************************
    Problem: 1061
    User: di4CoveRy
    Language: C++
    Result: Accepted
    Time:2152 ms
    Memory:5256 kb
****************************************************************/

#include <bits/stdc++.h>
#define INF (1<<29)
#define N 2050 
#define M 200050 using namespace std; typedef long long LL; int head[N],cnt=1,tot,S,T; int p[N],rp[N],L[N],a,b,c[N],d; LL dis[N]; int n,m,k; LL ans; inline int rd() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'
){x=x*10+ch-'0';ch=getchar();} return x*f; } struct Edge{ int a,b,v,cost,next; }e[M],id; inline void add(int a,int b,int v,int cost) { if (!a || !b) return ; e[++cnt] = (Edge){ a,b,v,cost,head[a] }, head[a] = cnt; e[++cnt] = (Edge){ b,a,0,-cost,head[b] },head[b] = cnt; } #define cp e[i].v
#define B e[i].b bool SPFA() { bool flag = false; for (int i=1;i<=tot;i++) p[i] = 0, dis[i] = (1LL<<62); dis[S] = 0; queue<int> q; q.push(S); while (!q.empty()) { int u = q.front(); q.pop(); if (u == T) flag = true; for (int i=head[u];i;i=e[i].next) if (cp > 0 && dis[u] + e[i].cost < dis[B]) { dis[B] = dis[u] + e[i].cost; p[B] = i; q.push(B); } } return flag; } void mcf() { int g = p[T] , flow = INF; while (g) { flow = min(flow , e[g].v); g = p[ e[g].a ]; } g = p[T]; while (g) { e[g ].v -= flow; e[g^1].v += flow; ans += 1LL * e[g].cost * flow; g = p[ e[g].a ]; } } int main() { n = rd(), m = rd(); for (int _=1;_<=n;_++) p[_] = rd(); for (int _=1;_<=n;_++) rp[_] = p[_]-p[_-1]; S = ++tot, T = ++tot; for (int _=0;_<=n+1;_++) L[_] = ++tot; for (int _=1;_<=n;_++) if (rp[_] > 0) add(S, L[_], rp[_], 0); else add(L[_], T, -rp[_], 0); for (int _=1;_<=n;_++) add(L[_+1], L[_], INF, 0); add(L[n+1], T, p[n], 0); for (int _=1;_<=m;_++) { int a = rd(), b = rd(), v = rd(); add(L[a], L[b+1], INF, v); } while (SPFA()) mcf(); cout << ans << endl; return 0; }