POJ 3614 - Sunscreen
http://poj.org/problem?id=3614
概要
C 頭の牛がおり,それぞれ SPF の値が minSPF[i] 以上 maxSPF[i] 以下の日焼止めを必要としている. 日焼止めは L 個あり,それぞれ SPF の値は SPF[i] で,cover[i] 頭の牛に塗ることができる.
このとき,最大で何頭の牛の要求を満たせるかを答える.
制約
- 1 <= C <= 2500
- 1 <= L <= 2500
- 1 <= minSPF[i] <= 1000
- minSPF[i] <= maxSPF[i] <= 1000
- 1 <= SPF[i] <= 1000
解法
普通(?)に最大流だけど,ノード数が最大で V = C+L+2 = 5002,エッジ数が最大で E = C + C*L + L = 6,255,000 と大きめなので実装に注意が要る.
アルゴリズムは Dinic を使って TLE を回避し,グラフは隣接リストで表現して容量やフローも V * V の配列ではなくエッジに持たせるようにして MLE を回避した.
poj/3614.cc1 #include <cstdio> 2 #include <vector> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 static const int MAXN = 2500 + 2500 + 2; 7 static const int INF = 10000000; 8 9 template <class Flow> 10 struct edge 11 { 12 int id; 13 Flow capacity, flow; 14 int back; 15 edge(int i, Flow c, int b) : id(i), capacity(c), flow(0), back(b) {} 16 }; 17 18 template <class Flow> 19 void make_edge(vector<edge<Flow> > *g, int src, int dst, Flow c) 20 { 21 const int i = g[src].size(), j = g[dst].size(); 22 g[src].push_back(edge<Flow>(dst, c, j)); 23 g[dst].push_back(edge<Flow>(src, 0, i)); 24 } 25 26 template <class Flow> 27 Flow dinic_augment(vector<edge<Flow> > *g, int N, int *level, bool *finished, int u, int sink, int cur)/*{{{*/ 28 { 29 if (u == sink || cur == 0) { 30 return cur; 31 } 32 if (finished[u]) { 33 return 0; 34 } 35 finished[u] = true; 36 for (typename vector<edge<Flow> >::iterator it = g[u].begin(); it != g[u].end(); ++it) { 37 const int v = it->id; 38 if (it->capacity - it->flow > 0 && level[v] > level[u]) { 39 const int f = dinic_augment(g, N, level, finished, v, sink, min(cur, it->capacity - it->flow)); 40 if (f > 0) { 41 it->flow += f; 42 g[v][it->back].flow -= f; 43 finished[u] = false; 44 return f; 45 } 46 } 47 } 48 return 0; 49 }/*}}}*/ 50 template <class Flow> 51 Flow dinic(vector<edge<Flow> > *g, int N, int source, int sink)/*{{{*/ 52 { 53 Flow max_flow = 0; 54 55 while (true) { 56 static int level[MAXN]; 57 fill_n(level, N, -1); 58 level[source] = 0; 59 queue<int> q; 60 q.push(source); 61 62 int d = N; 63 while (!q.empty() && level[q.front()] < d) { 64 const int u = q.front(); 65 q.pop(); 66 67 if (u == sink) { 68 d = level[u]; 69 } 70 for (typename vector<edge<Flow> >::iterator it = g[u].begin(); it != g[u].end(); ++it) { 71 const int v = it->id; 72 if (level[v] < 0 && it->capacity - it->flow > 0) { 73 q.push(v); 74 level[v] = level[u] + 1; 75 } 76 } 77 } 78 79 static bool finished[MAXN]; 80 fill_n(finished, N, false); 81 bool updated = false; 82 while (true) { 83 const int f = dinic_augment(g, N, level, finished, source, sink, INF); 84 if (f == 0) { 85 break; 86 } 87 max_flow += f; 88 updated = true; 89 } 90 91 if (!updated) { 92 break; 93 } 94 } 95 96 return max_flow; 97 }/*}}}*/ 98 99 int main() 100 { 101 int C, L; 102 scanf("%d %d", &C, &L); 103 static pair<int,int> cows[2500]; 104 static vector<edge<int> > g[MAXN]; 105 const int source = C+L, sink = source+1; 106 for (int i = 0; i < C; i++) { 107 scanf("%d %d", &cows[i].first, &cows[i].second); 108 make_edge(g, i, sink, 1); 109 } 110 for (int j = 0; j < L; j++) { 111 int s, p; 112 scanf("%d %d", &s, &p); 113 make_edge(g, source, C+j, p); 114 for (int i = 0; i < C; i++) { 115 if (cows[i].first <= s && s <= cows[i].second) { 116 make_edge(g, C+j, i, 1); 117 } 118 } 119 } 120 printf("%d\n", dinic(g, C+L+2, source, sink)); 121 return 0; 122 }