LOJ#2134 小园丁与老司机

我的妈呀,这码农神题......

第一问是个DP,要记录方案。先把纵向的转移建图。发现可以按照y坐标来划分阶段,每一层vector存一下,用前后缀最大值来转移。

第二问考虑所有可能成为最优方案的边。从终点倒推可以保证每条边都能到起点,而从起点出发就不一定能保证。这些边拿去网络流建图,然后最小流。

注意第二问找边的时候,每一层的点其实可以视作两个,经过同层转移的和未经过的。这两者不可混为一谈。

最小流先跑S -> T然后t -> s退流的话,要用当前弧优化,否则会被最后一个数据卡成n²。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 50010, INF = 0x7f7f7f7f;
  4 
  5 struct Node {
  6     int x, y, id;
  7     inline bool operator <(const Node &w) const {
  8         if(y != w.y) return y < w.y;
  9         return x < w.x;
 10     }
 11 }node[N];
 12 
 13 inline void read(int &x) {
 14     x = 0;
 15     char c = getchar();
 16     bool f = 0;
 17     while(c < '0' || c > '9') {
 18         if(c == '-') f = 1;
 19         c = getchar();
 20     }
 21     while(c >= '0' && c <= '9') {
 22         x = x * 10 + c - 48;
 23         c = getchar();
 24     }
 25     if(f) x = (~x) + 1;
 26     return;
 27 }
 28 
 29 struct Edge {
 30     int nex, v;
 31 }edge[N << 2]; int tp;
 32 
 33 int n, X[N << 2], xx, bin[N << 2], e[N], fr1[N], fr2[N], fr_l[N], fr_r[N], large_l[N], large_r[N], f[N], ff[N];
 34 bool visit[N], visit2[N];
 35 std::vector<int> v[N << 2];
 36 
 37 inline void add(int x, int y) {
 38     tp++;
 39     edge[tp].v = y;
 40     edge[tp].nex = e[x];
 41     e[x] = tp;
 42     return;
 43 }
 44 
 45 void out(int x, int flag) {
 46     if(!node[x].id) return;
 47     if(flag == 1) {
 48         out(fr1[x], 2);
 49     }
 50     else {
 51         out(fr2[x], 1);
 52         int y = fr2[x], u = node[y].y;
 53         if(y == x) {
 54             printf("%d ", node[x].id);
 55         }
 56         else if(node[y].x > node[x].x) {
 57             for(int i = 0; i < (int)(v[u].size()); i++) {
 58                 if(node[v[u][i]].x >= node[y].x) {
 59                     printf("%d ", node[v[u][i]].id);
 60                 }
 61             }
 62             for(int i = v[u].size() - 1; i >= 0; i--) {
 63                 int temp = node[v[u][i]].x;
 64                 if(temp < node[y].x && temp >= node[x].x) {
 65                     printf("%d ", node[v[u][i]].id);
 66                 }
 67             }
 68         }
 69         else {
 70             for(int i = v[u].size() - 1; i >= 0; i--) {
 71                 if(node[v[u][i]].x <= node[y].x) {
 72                     printf("%d ", node[v[u][i]].id);
 73                 }
 74             }
 75             for(int i = 0; i < (int)(v[u].size()); i++) {
 76                 int temp = node[v[u][i]].x;
 77                 if(temp > node[y].x && temp <= node[x].x) {
 78                     printf("%d ", node[v[u][i]].id);
 79                 }
 80             }
 81         }
 82     }
 83     return;
 84 }
 85 
 86 namespace fl {
 87     struct Edge {
 88         int nex, v, c;
 89         Edge(int Nex = 0, int V = 0, int C = 0) {
 90             nex = Nex;
 91             v = V;
 92             c = C;
 93         }
 94     }edge[1000010]; int tp = 1;
 95     int e[N], vis[N], in[N], d[N], vis2[N], cur[N];
 96     std::queue<int> Q;
 97     inline void add(int x, int y, int z) {
 98         edge[++tp] = Edge(e[x], y, z);
 99         e[x] = tp;
100         edge[++tp] = Edge(e[y], x, 0);
101         e[y] = tp;
102         return;
103     }
104     inline void Add(int x, int y) {
105         /// x -> y [1, INF]
106         vis2[x] = vis2[y] = 1;
107         add(x, y, N);
108         in[y]++;
109         in[x]--;
110         return;
111     }
112     inline bool BFS(int s, int t) {
113         static int Time = 0; Time++;
114         vis[s] = Time;
115         d[s] = 0;
116         Q.push(s);
117         while(!Q.empty()) {
118             int x = Q.front();
119             Q.pop();
120             for(int i = e[x]; i; i = edge[i].nex) {
121                 int y = edge[i].v;
122                 if(vis[y] != Time && edge[i].c) {
123                     vis[y] = Time;
124                     d[y] = d[x] + 1;
125                     Q.push(y);
126                 }
127             }
128         }
129         return vis[t] == Time;
130     }
131     int DFS(int x, int t, int maxF) {
132         if(x == t) return maxF;
133         int ans = 0;
134         for(int i = cur[x] ? cur[x] : e[x]; i; i = edge[i].nex) {
135             int y = edge[i].v;
136             if(!edge[i].c || d[y] != d[x] + 1) {
137                 continue;
138             }
139             int temp = DFS(y, t, std::min(maxF - ans, edge[i].c));
140             if(!temp) d[y] = INF;
141             ans += temp;
142             edge[i].c -= temp;
143             edge[i ^ 1].c += temp;
144             if(ans == maxF) break;
145             cur[x] = i;
146         }
147         return ans;
148     }
149     inline int dinic(int s, int t) {
150         int ans = 0;
151         while(BFS(s, t)) {
152             memset(cur, 0, sizeof(cur));
153             ans += DFS(s, t, INF);
154         }
155         return ans;
156     }
157     inline void solve() {
158         int s = N - 5, t = N - 2, S = N - 3, T = N - 4;
159         for(int i = 1; i <= n; i++) {
160             if(!vis2[i]) continue;
161             add(s, i, N);
162             add(i, t, N);
163         }
164         int now = tp;
165         add(t, s, INF);
166         for(int i = 1; i <= n; i++) {
167             if(in[i] > 0) {
168                 add(S, i, in[i]);
169             }
170             else if(in[i] < 0) {
171                 add(i, T, -in[i]);
172             }
173         }
174         int ans;
175         dinic(S, T);
176         ans = edge[now + 2].c;
177         for(int i = now + 1; i <= tp; i++) edge[i].c = 0;
178         ans -= dinic(t, s);
179         printf("%d
", ans);
180         return;
181     }
182 }
183 
184 int main() {
185     read(n);
186     for(int i = 1; i <= n; i++) {
187         read(node[i].x); read(node[i].y);
188         node[i].id = i;
189         X[++xx] = node[i].x;
190         X[++xx] = node[i].y;
191         X[++xx] = node[i].x + node[i].y;
192         X[++xx] = node[i].x - node[i].y;
193     }
194     ++n; ++xx; /// the Node O
195     std::sort(node + 1, node + n + 1);
196     std::sort(X + 1, X + xx + 1);
197     xx = std::unique(X + 1, X + xx + 1) - X - 1;
198     for(int i = 1; i <= n; i++) {
199         int temp = std::lower_bound(X + 1, X + xx + 1, node[i].x + node[i].y) - X;
200         if(bin[temp]) {
201             add(bin[temp], i);
202         }
203         bin[temp] = i;
204     }
205     memset(bin + 1, 0, xx * sizeof(int));
206     for(int i = 1; i <= n; i++) {
207         int temp = std::lower_bound(X + 1, X + xx + 1, node[i].x - node[i].y) - X;
208         if(bin[temp]) {
209             add(bin[temp], i);
210         }
211         bin[temp] = i;
212     }
213     memset(bin + 1, 0, xx * sizeof(int));
214     for(int i = 1; i <= n; i++) {
215         node[i].x = std::lower_bound(X + 1, X + xx + 1, node[i].x) - X;
216         node[i].y = std::lower_bound(X + 1, X + xx + 1, node[i].y) - X;
217     }
218     for(int i = 1; i <= n; i++) {
219         if(bin[node[i].x]) {
220             add(bin[node[i].x], i);
221         }
222         bin[node[i].x] = i;
223         v[node[i].y].push_back(i);
224     }
225     /// Build Graph 1 Over
226     memset(f, ~0x3f, sizeof(f));
227     f[1] = 0;
228     for(int u = 1; u <= xx; u++) {
229         if(!v[u].size()) continue;
230         int len = v[u].size();
231         for(int i = 0; i < len; i++) {
232             int x = v[u][i];
233             ff[x] = f[x];
234             fr2[x] = x;
235         }
236         /// trans in row
237         for(int i = 0; i < len; i++) {
238             int x = v[u][i];
239             if(i && f[x] < large_l[i - 1]) {
240                 large_l[i] = large_l[i - 1];
241                 fr_l[i] = fr_l[i - 1];
242             }
243             else {
244                 large_l[i] = f[x];
245                 fr_l[i] = x;
246             }
247         }
248         for(int i = len - 1; i >= 0; i--) {
249             int x = v[u][i];
250             if(i < len - 1 && f[x] < large_r[i + 1]) {
251                 large_r[i] = large_r[i + 1];
252                 fr_r[i] = fr_r[i + 1];
253             }
254             else {
255                 large_r[i] = f[x];
256                 fr_r[i] = x;
257             }
258         }
259         for(int i = 0; i < len; i++) {
260             int x = v[u][i];
261             if(i < len - 1 && f[x] < large_r[i + 1] + len - i - 1) {
262                 f[x] = large_r[i + 1] + len - i - 1;
263                 fr2[x] = fr_r[i + 1];
264             }
265             if(i && f[x] < large_l[i - 1] + i) {
266                 f[x] = large_l[i - 1] + i;
267                 fr2[x] = fr_l[i - 1];
268             }
269         }
270         /// trans in cross / other
271         for(int i = 0; i < len; i++) {
272             int x = v[u][i];
273             for(int i = e[x]; i; i = edge[i].nex) {
274                 int y = edge[i].v;
275                 if(f[y] < f[x] + 1) {
276                     f[y] = f[x] + 1;
277                     fr1[y] = x;
278                 }
279             }
280         }
281     }
282     /// DP OVER
283     int large_val = -INF, ans_pos = 0;
284     for(int i = 1; i <= n; i++) {
285         if(large_val < f[i]) {
286             large_val = f[i];
287             ans_pos = i;
288         }
289     }
290     printf("%d
", large_val);
291     out(ans_pos, 2);
292     /// Out OVER
293     for(int i = 1; i <= n; i++) {
294         if(f[i] == large_val) visit2[i] = 1;
295         if(ff[i] == large_val) visit[i] = 1;
296     }
297     for(int u = xx; u >= 1; u--) {
298         if(!v[u].size()) continue;
299         int len = v[u].size();
300         /// build Flow Graph (this -> up)
301         for(int i = 0; i < len; i++) {
302             int x = v[u][i];
303             for(int i = e[x]; i; i = edge[i].nex) {
304                 int y = edge[i].v;
305                 if(visit[y] && ff[y] == f[x] + 1) {
306                     visit2[x] = 1;
307                     fl::Add(x, y);
308                 }
309             }
310             if(visit2[x] && f[x] == ff[x]) {
311                 visit[x] = 1;
312             }
313         }
314         /// Find Edge in row (update)
315         for(int j = 0; j < len; j++) {
316             int y = v[u][j];
317             if(!visit2[y]) continue;
318             for(int i = 0; i < len; i++) {
319                 int x = v[u][i];
320                 if(visit[x]) continue;
321                 /// x -> y
322                 if(node[x].x < node[y].x && f[y] == ff[x] + j) {
323                     visit[x] = 1;
324                 }
325                 else if(node[y].x < node[x].x && f[y] == ff[x] + len - j - 1) {
326                     visit[x] = 1;
327                 }
328             }
329         }
330     }
331     puts("");
332     /// Build Flow Over
333     fl::solve();
334     return 0;
335 }
AC代码

10k还行

原文地址:https://www.cnblogs.com/huyufeifei/p/10580049.html