【题解】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\n", ans + Max_Flow());
    return 0;
}

 

posted @ 2019-02-14 21:57  Twilight_Sx  阅读(152)  评论(0编辑  收藏  举报