467 字
2 分钟
[bzoj 1449] [JSOI2009] 球队收益
Description
Input
Output
一个整数表示联盟里所有球队收益之和的最小值。
Sample Input
3 3
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1
Sample Output
43
HINT
题解懒得写了
/* * @Author: WildRage * @Date: 2017-07-29 15:51:58 * @Last Modified by: WildRage * @Last Modified time: 2017-07-29 16:05:11 */#include <cstdio>#include <queue>#include <cstring>using namespace std;int win[5005], lose[5005];int C[5005], D[5005], du[5005];const int INF = 0x3f3f3f3f;class Mincost{ public: int first[20005], p; Mincost() { memset(first, -1, sizeof(first)); } class edge { public: int END, S, next, cap, cost; } v[100005];
void add(int a, int b, int f, int c) { v[p].END = b, v[p].next = first[a], v[p].S = a, v[p].cap = f, v[p].cost = c, first[a] = p++; v[p].END = a, v[p].next = first[b], v[p].S = b, v[p].cap = 0, v[p].cost = -c, first[b] = p++; } int dis[20005], pre[20005]; bool vis[20005]; bool spfa(int S, int E) { memset(dis, 0x3f, sizeof(dis)); memset(pre, -1, sizeof(pre)); memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(S); vis[S] = 1; dis[S] = 0; while (!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = 0; for (int i = first[u]; i != -1; i = v[i].next) { if (!v[i].cap) continue; if (dis[v[i].END] > dis[u] + v[i].cost) { dis[v[i].END] = dis[u] + v[i].cost; pre[v[i].END] = i; if (!vis[v[i].END]) { vis[v[i].END] = 1; Q.push(v[i].END); } } } } return dis[E] != 0x3f3f3f3f; } int MinCost(int S, int T) { int ans = 0, flow; while (spfa(S, T)) { flow = INF; for (int i = pre[T]; i != -1; i = pre[v[i].S]) flow = min(flow, v[i].cap); for (int i = pre[T]; i != -1; i = pre[v[i].S]) v[i].cap -= flow, v[i ^ 1].cap += flow; ans += dis[T] * flow; } return ans; }} Min;int main(int argc, char const *argv[]){ int n, m, a, b; int S = 0, T = 10005; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d%d%d%d", &win[i], &lose[i], &C[i], &D[i]); } int ans = 0; for (int i = 1; i <= m; i++) { Min.add(S, i, 1, 0); scanf("%d%d", &a, &b); Min.add(i, m + a, 1, 0); Min.add(i, m + b, 1, 0); du[a]++, du[b]++; } for (int i = 1; i <= n; i++) lose[i] += du[i]; for (int i = 1; i <= n; i++) ans += lose[i] * lose[i] * D[i] + win[i] * win[i] * C[i]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= du[i]; j++) { Min.add(m + i, T, 1, 2 * win[i] * C[i] + C[i] + D[i] - 2 * lose[i] * D[i]); lose[i]--; win[i]++; } } printf("%d\n", ans + Min.MinCost(S, T)); //while (1) ; return 0;}
[bzoj 1449] [JSOI2009] 球队收益
https://www.nekomio.com/posts/51/