zoukankan      html  css  js  c++  java
  • BZOJ1930 [Shoi2003]pacman 吃豆豆

    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
    ", -work());
    117     return 0;
    118 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    C# 使用HttpWebRequest Post提交数据,携带Cookie和相关参数示例
    关于vue的页面跳转后,如何每次进入页面时都能获取后台数据
    关于vue的页面跳转后,如何每次进入页面时都能获取后台数据
    C#根据汉字获取编码和根据编码获取汉字
    C#根据汉字获取编码和根据编码获取汉字
    多线程系列教材 (一)- Java 创建一个线程的三种方式
    Lambda系列教材 (三)- java 集合的聚合操作
    Lambda系列教材 (二)- 方法引用
    Lambda系列教材 (一)- Java Lambda 表达式教程
    泛型系列教材 (四)- Java 中的子类泛型 转型 成父类泛型
  • 原文地址:https://www.cnblogs.com/rausen/p/4297767.html
Copyright © 2011-2022 走看看