zoukankan      html  css  js  c++  java
  • BZOJ1520 [POI2006]Szk-Schools

    裸的费用流啊。。。

    建图:对于一个点p拆成两个p1和p2,S向p1连边,流量为1,费用为0;p2向T连边流量为1,费用为0

    然后i1向a2到b2分别连边,不妨设i1向p2连边,流量为1,费用为|i - p| * ki

    跑一下费用流,如果流量不为n,NIE!然后答案就是费用之和。。。

      1 /**************************************************************
      2     Problem: 1520
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:1296 ms
      7     Memory:2380 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12  
     13 using namespace std;
     14 const int N = 405;
     15 const int M = 1e5 + 5;
     16 const int inf = 1e9;
     17  
     18 struct edges {
     19     int next, to, f, cost;
     20     edges() {}
     21     edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
     22 } e[M];
     23   
     24 int n, S, T;
     25 int first[N], tot = 1;
     26 int q[N], d[N], g[N];
     27 bool v[N];
     28  
     29 inline int read() {
     30     int x = 0, sgn = 1;
     31     char ch = getchar();
     32     while (ch < '0' || '9' < ch) {
     33         if (ch == '-') sgn = -1;
     34         ch = getchar();
     35     }
     36     while ('0' <= ch && ch <= '9') {
     37         x = x * 10 + ch - '0';
     38         ch = getchar();
     39     }
     40     return sgn * x;
     41 }
     42  
     43 inline void Add_Edges(int x, int y, int f, int c) {
     44     e[++tot] = edges(first[x], y, f, c), first[x] = tot;
     45     e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
     46 }
     47   
     48 inline int calc() {
     49     int flow = inf, x;
     50     for (x = g[T]; x; x = g[e[x ^ 1].to])
     51         flow = min(flow, e[x].f);
     52     for (x = g[T]; x; x = g[e[x ^ 1].to])
     53         e[x].f -= flow, e[x ^ 1].f += flow;
     54     return flow;
     55 }
     56  
     57 #define y e[x].to
     58 bool spfa() {
     59     int x, now, l, r;
     60     for (x = 1; x <= T; ++x)
     61         d[x] = inf;
     62     d[S] = 0, v[S] = 1, q[0] = S;
     63     for(l = r = 0; l != (r + 1) % N; ) {
     64         now = q[l], ++l %= N;
     65         for (x = first[now]; x; x = e[x].next) {
     66             if (d[now] + e[x].cost < d[y] && e[x].f) {
     67                 d[y] = d[now] + e[x].cost, g[y] = x;
     68                 if (!v[y]) {
     69                     v[y] = 1;
     70                     if (d[y] < d[q[l]])
     71                         q[(l += N - 1) %= N] = y;
     72                     else q[++r %= N] = y;
     73                 }
     74             }
     75         }
     76         v[now] = 0;
     77     }
     78     return d[T] != inf;
     79 }
     80 #undef y
     81  
     82 inline int work() {
     83     static int res, tot;
     84     res = 0, tot = 0;
     85     while (spfa()) {
     86         tot += calc();
     87         res += d[T];
     88     }
     89     if (tot == n) printf("%d
    ", res);
     90     else puts("NIE");
     91 }
     92  
     93 int main() {
     94     int i, j, a, b, k, m;
     95     n = read(), S = 2 * n + 1, T = S + 1;
     96     for (i = 1; i <= n; ++i)
     97         Add_Edges(S, i, 1, 0), Add_Edges(i + n, T, 1, 0);
     98     for (i = 1; i <= n; ++i) {
     99         m = read(), a = read(), b = read(), k = read();
    100         for (j = a; j <= b; ++j)
    101             Add_Edges(i, n + j, 1, abs((j - m) * k));
    102     }
    103     work();
    104     return 0;
    105 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    「BZOJ 1000」A+B Problem
    「HNOI 2008」越狱
    蓝桥杯 拼音字母
    蓝桥杯 抽签
    蓝桥杯 快速排序
    [蓝桥杯] 最大比例
    [蓝桥杯] 交换瓶子
    [蓝桥杯] 四平方和
    [蓝桥杯] 剪邮票
    [蓝桥杯] 方格填数
  • 原文地址:https://www.cnblogs.com/rausen/p/4356480.html
Copyright © 2011-2022 走看看