裸的费用流啊。。。
建图:对于一个点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 }