P2887 [USACO07NOV]防晒霜Sunscreen

总感觉贪心哪里不对, 写了个网络流水过去了此题.
建图不难, 从源点向每一种防晒霜连一条容量为防晒霜数量的边, 再 \(O(N^2)\) 地从每一种防晒霜向可行的牛连一条容量为1的边, 最后从每头牛向汇点连一条容量为1的边.

#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> P;
const int MAXN = 2500 + 10;
inline int read(){
    char ch = getchar(); int x = 0;
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    return x;
}

int C, L;

namespace dinic
{
    struct edge
    {
        int to, cap, rev;
    };vector<edge> g[MAXN << 1];

    int S, T;
    int iter[MAXN << 1], level[MAXN << 1];

    inline void addedge(int u, int v, int c) {
        g[u].push_back((edge) {v, c, g[v].size()});
        g[v].push_back((edge) {u, 0, g[u].size() - 1});
    }

    inline bool bfs() {
        memset(level, 0, sizeof(level));
        queue<int> q;
        q.push(S), level[S] = 1;

        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int i = 0; i < (int) g[u].size(); i++) {
                edge &e = g[u][i];
                if(e.cap && !level[e.to])
                    level[e.to] = level[u] + 1, q.push(e.to);
            }
        }
        return level[T];
    }

    int dfs(int u, int flow) {
        if(u == T) return flow;
        for(int &i = iter[u]; i < (int) g[u].size(); i++) {
            edge &e = g[u][i];
            if(e.cap && level[e.to] == level[u] + 1) {
                int d = dfs(e.to, min(flow, e.cap));
                if(d) {
                    e.cap -= d, g[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

    int maxflow(int s, int t) {
        S = s, T = t; int ans = 0, d = 0;
        while(bfs()) {
            memset(iter, 0, sizeof(iter));
            while(d = dfs(S, (1 << 30)), d) ans += d;
        }
        return ans;
    }
}

P a[MAXN];

int main(){
    cin>>C>>L;
    for(int i = 1; i <= C; i++)
        a[i].first = read(), a[i].second = read();
    for(int i = L + 1; i <= C + L; i++) 
        dinic::addedge(i, L + C + 1, 1);

    for(int i = 1; i <= L; i++) {
        int spf = read(), cov = read();
        dinic::addedge(0, i, cov);

        for(int j = 1; j <= C; j++) 
            if(a[j].first <= spf && spf <= a[j].second)
                dinic::addedge(i, j + L, 1);
    }
    printf("%d\n", dinic::maxflow(0, L + C + 1));
    return 0;
}
posted @ 2018-10-29 12:07  俺是小程  阅读(206)  评论(0编辑  收藏  举报