SHOI出过这么鬼的题?、、跪

首先我们可以想到费用网络流,找一个流量为2的最大费用流即可,问题是怎么建图

因为针对点才有收益,而且收益只有一次,所以考虑拆点,不妨设一个点p拆成入点p1和出点p2

则p1 -> p2连边流量为1,费用为1;再连边流量为1,费用为0;S向p1连边流量为1,费用为0;p2向T连边,流量为1,费用为0

若p能到达q,则p2 -> q1连边,流量为2,费用为0

然后会发现边太多。。。优化?

如果i能到达j,j能到达k,则i不要向k连边,于是就是一个单调性的问题,对点按x轴排序,然后按照y轴单调增加的方式连边。

 

  1 /**************************************************************
  2     Problem: 1930
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:192 ms
  7     Memory:63416 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <algorithm>
 12  
 13 using namespace std;
 14 const int N = 2015;
 15 const int M = 4e6 + 5;
 16 const int inf = 1e9;
 17  
 18 inline int read() {
 19     int x = 0;
 20     char ch = getchar();
 21     while (ch < '0' || '9' < ch)
 22         ch = getchar();
 23     while ('0' <= ch && ch <= '9') {
 24         x = x * 10 + ch - '0';
 25         ch = getchar();
 26     }
 27     return x;
 28 }
 29  
 30 struct point {
 31     int x, y;
 32      
 33     inline void read_in() {
 34         x = read(), y = read();
 35     }
 36     inline bool operator < (const point &p) const {
 37         return x == p.x ? y < p.y : x < p.x;
 38     }
 39 } p[N];
 40  
 41 struct edges {
 42     int next, to, f, cost;
 43     edges() {}
 44     edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
 45 } e[M];
 46  
 47 int n, S, S1, T;
 48 int first[N << 1], tot = 1;
 49 int a[N];
 50 int d[N << 1], g[N << 1], q[N << 1], vis[N << 1];
 51 bool v[N << 1];
 52  
 53 inline void Add_Edges(int x, int y, int f, int c) {
 54     e[++tot] = edges(first[x], y, f, c), first[x] = tot;
 55     e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
 56 }
 57   
 58 inline int calc() {
 59     int flow = inf, x;
 60     for (x = g[T]; x; x = g[e[x ^ 1].to])
 61         flow = min(flow, e[x].f);
 62     for (x = g[T]; x; x = g[e[x ^ 1].to])
 63         e[x].f -= flow, e[x ^ 1].f += flow;
 64     return flow;
 65 }
 66  
 67 #define y e[x].to
 68 bool spfa() {
 69     int x, now, l, r;
 70     for (x = 1; x <= S1; ++x)
 71         d[x] = inf;
 72     d[S] = 0, v[S] = 1, q[0] = S;
 73     for(l = r = 0; l != (r + 1) % N; ) {
 74         now = q[l], ++l %= N;
 75         for (x = first[now]; x; x = e[x].next) {
 76             if (d[now] + e[x].cost < d[y] && e[x].f) {
 77                 d[y] = d[now] + e[x].cost, g[y] = x;
 78                 if (!v[y]) {
 79                     v[y] = 1;
 80                     if (d[y] < d[q[l]])
 81                         q[(l += N - 1) %= N] = y;
 82                     else q[++r %= N] = y;
 83                 }
 84             }
 85         }
 86         v[now] = 0;
 87     }
 88     return d[T] != inf;
 89 }
 90 #undef y
 91  
 92 inline int work() {
 93     int res = 0;
 94     while (spfa())
 95         res += calc() * d[T];
 96     return res;
 97 }
 98  
 99 #define p1(i) (i << 1) - 1
100 #define p2(i) (i << 1)
101 int main() {    
102     int i, j, tmp;
103     n = read(), S = n * 2 + 1, T = S + 1, S1 = T + 1;
104     for (i = 1; i <= n; ++i)
105         p[i].read_in();
106     sort(p + 1, p + n + 1);
107     for (i = 1; i <= n; ++i) {
108         a[i] = p[i].y, tmp = -1;
109         Add_Edges(S1, p1(i), 1, 0), Add_Edges(p2(i), T, 1, 0);
110         Add_Edges(p1(i), p2(i), 1, -1), Add_Edges(p1(i), p2(i), 1, 0);
111         for (j = i - 1; j; --j)
112             if (a[j] <= a[i] && a[j] > tmp)
113                 tmp = a[j], Add_Edges(p2(j), p1(i), 2, 0);
114     }
115     Add_Edges(S, S1, 2, 0);
116     printf("%d\n", -work());
117     return 0;
118 }
View Code

 

posted on 2015-02-22 22:01  Xs酱~  阅读(227)  评论(0编辑  收藏  举报