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轴单调增加的方式连边。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen