zoukankan      html  css  js  c++  java
  • bzoj1449 [JSOI2009]球队收益

    1449: [JSOI2009]球队收益

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 1131  Solved: 640
    [Submit][Status][Discuss]

    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

    分析:很妙的idea.

       首先要能想到用最小费用最大流求解. 为什么呢?把比赛当作点,每一场比赛有两种结果,那么就可以认为容量为1. 要使得收益最小,加上费用,就是求最小费用最大流了.但是确定不了每场比赛的收益. 

       一个非常巧妙的做法:

       我们考虑费用的增量:多赢一场比赛产生的收益。
       即(C(w + 1)^2 + D(l − 1)^2 ) − (Cw^2 + Dl^2 ) = 2wC − 2lD + C + D。
       对于第i支队伍,假设后m场中i参加的有x场,那么最初w = win,
       l = lose + x,之后每赢一场w + +,l − −。我们从第i支队伍的点向汇连x条边,
       分别代表第i支队伍赢了j场比赛时相对赢j − 1场时收益的增量。由于增量一定
       越来越大(平方嘛),所以流量最先流过的一定是费用较小的边,即j最小的边。
       答案即所有队伍最初收益+最小费用最大流的费用。

       费用递增模型可以采用拆边的方式跑费用流. 先确定最初状态,保证以后的费用都是递增的,这是算法正确性的保证!

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 10010,inf = 0x7fffffff;
    int n,m,win[maxn],lose[maxn],c[maxn],d[maxn];
    int a[maxn],b[maxn],ans,S,T,vis[maxn],vis2[maxn];
    int head[maxn],to[maxn * 6],nextt[maxn * 6],w[maxn * 6],cost[maxn * 6],tot = 2;
    
    void add(int x,int y,int z,int p)
    {
        w[tot] = z;
        cost[tot] = p;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    
        w[tot] = 0;
        cost[tot] = -p;
        to[tot] = x;
        nextt[tot] = head[y];
        head[y] = tot++;
    }
    
    bool spfa()
    {
        queue <int> q;
        memset(vis,0,sizeof(vis));
        memset(vis2,0,sizeof(vis2));
        for (int i = 1; i <= T; i++)
            d[i] = inf;
        d[S] = 0;
        vis[S] = 1;
        q.push(S);
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (w[i] && d[v] > d[u] + cost[i])
                {
                    d[v] = d[u] + cost[i];
                    if (!vis[v])
                    {
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return d[T] < inf;
    }
    
    int dfs(int u,int f)
    {
        if (u == T)
        {
            ans += f * d[u];
            return f;
        }
        int res = 0;
        vis2[u] = 1;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (w[i] && !vis2[v] && d[v] == d[u] + cost[i])
            {
                int temp = dfs(v,min(f - res,w[i]));
                w[i] -= temp;
                w[i ^ 1] += temp;
                res += temp;
                if (res == f)
                    return res;
            }
        }
        return res;
    }
    
    void dinic()
    {
        while(spfa())
            dfs(S,inf);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        S = n + m + 1;
        T = S + 1;
        for (int i = 1; i <= n; i++)
            scanf("%d%d%d%d",&win[i],&lose[i],&c[i],&d[i]);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            lose[a[i]]++;
            lose[b[i]]++;
        }
        for (int i = 1; i <= n; i++)
            ans += win[i] * win[i] * c[i] + lose[i] * lose[i] * d[i];
        for (int i = 1; i <= m; i++)
        {
            add(S,i,1,0);
            add(i,a[i] + m,1,0);
            add(i,b[i] + m,1,0);
            add(a[i] + m,T,1,c[a[i]] * (2 * win[a[i]] + 1) - d[a[i]] * (2 * lose[a[i]] - 1));
            win[a[i]]++;
            lose[a[i]]--;
            add(b[i] + m,T,1,c[b[i]] * (2 * win[b[i]] + 1) - d[b[i]] * (2 * lose[b[i]] - 1));
            win[b[i]]++;
            lose[b[i]]--;
        }
        dinic();
        printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    WPF 从文件加载字体
    WPF 从文件加载字体
    WPF 从文件加载字体
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    PHP date_parse_from_format() 函数
    PHP date_offset_get() 函数
    PHP date_modify() 函数
    PHP date_isodate_set() 函数
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8595217.html
Copyright © 2011-2022 走看看