467 字
2 分钟
[bzoj 1449] [JSOI2009] 球队收益
2017-07-30

Description#

645602374fcf3.gif

Input#

72452186e227.gif

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#

469131504db0e.gif

题解懒得写了#

/*
 * @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/
作者
NekoMio
发布于
2017-07-30
许可协议
CC BY-NC-SA 4.0