bzoj 1930: [Shoi2003]pacman 吃豆豆 [費用流]

Candy?發表於2017-05-14

1930: [Shoi2003]pacman 吃豆豆

題意:兩個PACMAN吃豆豆。一開始的時候,PACMAN都在座標原點的左下方,豆豆都在右上方。PACMAN走到豆豆處就會吃掉它。PACMAN行走的路線很奇怪,只能向右走或者向上走,他們行走的路線不可以相交。 請你幫這兩個PACMAN計算一下,他們倆加起來最多能吃掉多少豆豆。


暴力建圖會被卡記憶體,可以按lis剖分建圖...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define fir first
#define sec second
const int N = 5005, M = 1e6+5, mo = 1e9+7;
inline int read() {
    char c=getchar(); int x=0,f=1;
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n, s, t, ss, tt;
struct meow {
    int x, y;
    bool operator <(const meow &r) const {return x == r.x ? y < r.y : x < r.x;}
} a[2005];

struct edge {int v, ne, c, f, w;} e[M];
int cnt = 1, h[N];
inline void ins(int u, int v, int c, int w) { //printf("ins %d --> %d\n", u, v);
    e[++cnt] = (edge) {v, h[u], c, 0, w};  h[u] = cnt;
    e[++cnt] = (edge) {u, h[v], 0, 0, -w}; h[v] = cnt;
}

void build() {
    s=0; ss=n+n+1; tt=n+n+2; t=n+n+3;
    ins(s, ss, 2, 0); ins(tt, t, 2, 0);
    static bool mark[N];
    for(int i=1; i<=n; i++) {
        ins(i, n+i, 1, 1); ins(i, n+i, 1, 0);
        int high = 0;
        for(int j=i-1; j>=1; j--) 
            if(a[j].y > high && a[j].y <= a[i].y) ins(j+n, i, 2, 0), high = a[j].y, mark[j] = 1;
        if(!high) ins(ss, i, 2, 0);
    }
    for(int i=1; i<=n; i++) if(!mark[i]) ins(i+n, tt, 2, 0);
}
namespace flow {
    int d[N], inq[N], q[N], head, tail; 
    pair<int, int> pre[N];
    inline void lop(int &x) {if(x == N) x = 1; else if(x == 0) x = N-1;}
    bool spfa() {
        head = tail = 1;
        //memset(d, -1, sizeof(d));
        for(int i=s; i<=t; i++) d[i] = -1e9;
        memset(inq, 0, sizeof(inq));
        d[s] = 0; q[tail++] = s; inq[s] = 1;
        pre[t].fir = -1;
        while(head != tail) {
            int u = q[head++]; inq[u] = 0; lop(head); 
            for(int i=h[u]; i; i=e[i].ne) if(e[i].c > e[i].f) {
                int v = e[i].v;
                if(d[v] < d[u] + e[i].w) {
                    d[v] = d[u] + e[i].w;
                    pre[v] = make_pair(u, i);
                    if(!inq[v]) {
                        inq[v] = 1;
                        //if(d[v] > d[q[head]]) head--, lop(head), q[head] = v;
                        //else q[tail++] = v, lop(tail);
                        q[tail++] = v; lop(tail);
                    }
                }
            }
        }
        return pre[t].fir != -1;
    }
    int mcmf() {
        int flow = 0, cost = 0;
        while(spfa()) {
            int f = 1e9, x;
            for(int i=t; i != s; i = pre[i].fir) x = pre[i].sec, f = min(f, e[x].c - e[x].f);
            flow += f; cost += d[t] * f; 
            for(int i=t; i != s; i = pre[i].fir) x = pre[i].sec, e[x].f += f, e[x^1].f -= f;
        }
        return cost;
    }
}
void print(meow &a) {printf("(%d, %d)\n", a.x, a.y);}
int main() {
    freopen("in", "r", stdin);
    n = read();
    for(int i=1; i<=n; i++) a[i].x = read(), a[i].y = read();
    sort(a+1, a+n+1);
    //for(int i=1; i<=n; i++) print(a[i]);
    build();
    int ans = flow::mcmf();
    printf("%d\n", ans);
}

相關文章