题解JSOI2009球队收益 / 球队预算
Posted Twilight_Sx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解JSOI2009球队收益 / 球队预算相关的知识,希望对你有一定的参考价值。
为什么大家都不写把输的场次增加的呢?我一定要让大家知道,这并没有什么关系~所以 (C[i] <= D[i]) 的条件就是来卖萌哒??
#include <bits/stdc++.h> using namespace std; #define maxn 1000000 #define INF 99999999 int 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 ", ans + Max_Flow()); return 0; }
以上是关于题解JSOI2009球队收益 / 球队预算的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1449/2895[JSOI2009]球队收益/球队预算 最小费用最大流