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