【题解】JSOI2009球队收益 / 球队预算

  为什么大家都不写把输的场次增加的呢?我一定要让大家知道,这并没有什么关系~所以 \(C[i] <= D[i]\) 的条件就是来卖萌哒??

#include <bits/stdc++.h>using namespace std;#define maxn 1000000#define INF 99999999int n, m, S, T, rec[maxn], flow[maxn], a[maxn], b[maxn];int ans, tot, c[maxn], d[maxn], dis[maxn], num[maxn];bool vis[maxn];int read() { int x = 0, k = 1; char c; c = getchar(); while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); } while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * k;}struct edge { int cnp, to[maxn], last[maxn], head[maxn], f[maxn], co[maxn]; edge() { cnp = 2; } void add(int u, int v, int fl, int w) { to[cnp] = v, f[cnp] = fl, co[cnp] = w, last[cnp] = head[u], head[u] = cnp ++; to[cnp] = u, f[cnp] = 0, co[cnp] = -w, last[cnp] = head[v], head[v] = cnp ++; }}E1;struct node { int x, y;}P[maxn];int multi(int x) { return x * x; }void Build() { S = 0, T = 3 * m + 3; for(int i = 1; i <= n; i ++) { int A = a[i] + num[i], B = b[i]; if(num[i]) rec[i] = tot + 1; for(int j = 1; j <= num[i]; j ++) { ++ tot; E1.add(tot, T, 1, 2 * B * d[i] - 2 * A * c[i] + c[i] + d[i]); if(j != num[i]) E1.add(tot, tot + 1, INF, 0); A --, B ++; } } for(int i = 1; i <= m; i ++) { E1.add(S, ++ tot, 1, 0); E1.add(tot, rec[P[i].x], 1, 0); E1.add(tot, rec[P[i].y], 1, 0); }}bool SPFA() { queue <int> q; for(int i = 0; i <= T; i ++) dis[i] = INF, vis[i] = 0; q.push(S); dis[S] = 0; flow[S] = INF; while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = E1.head[u]; i; i = E1.last[i]) { int v = E1.to[i]; if(!E1.f[i]) continue; if(dis[v] > dis[u] + E1.co[i]) { dis[v] = dis[u] + E1.co[i]; rec[v] = i, flow[v] = min(flow[u], E1.f[i]); if(!vis[v]) q.push(v), vis[v] = 1; } } } if(dis[T] != INF) return 1; return 0;}int Max_Flow() { int ans = 0, cost = 0; while(SPFA()) { int u = T; while(u != S) { int t = rec[u]; E1.f[t] -= flow[T], E1.f[t ^ 1] += flow[T]; u = E1.to[t ^ 1]; } ans += flow[T], cost += dis[T] * flow[T]; } return cost;}int main() { n = read(), m = read(); for(int i = 1; i <= n; i ++) { a[i] = read(), b[i] = read(), c[i] = read(), d[i] = read(); } for(int i = 1; i <= m; i ++) { int x = read(), y = read(); num[x] ++, num[y] ++; P[i].x = x, P[i].y = y; } for(int i = 1; i <= n; i ++) ans += c[i] * multi(a[i] + num[i]) + d[i] * multi(b[i]); Build(); printf("%d\n", ans + Max_Flow()); return 0;}

 

相关文章