BZOJ 1449: [JSOI2009]球队收益 最小费用最大流

title

\(~\)
BZOJ 1449
LUOGU 4307
Description

在一个篮球联赛里,有 \(n\) 支球队,球队的支出是和他们的胜负场次有关系的,具体来说,第 \(i\) 支球队的赛季总支出是\(C_i\times x^2+D_i \times y^2,D_i \le C_i\) 。(赢得多,给球员的奖金就多嘛) 其中 \(x,y\) 分别表示这只球队本赛季的胜负场次。现在赛季进行到了一半,每只球队分别取得了 \(a_i\) 场胜利和 \(b_i\) 场失利。而接下来还有 \(m\) 场比赛要进行。问联盟球队的最小总支出是多少。

Input

第一行 \(n,m\)
接下来 \(n\) 行每行 \(4\) 个整数 \(a_i,b_i,C_i,D_i\)
再接下来 \(m\) 行每行两个整数 \(s\)\(t\) 表示第 \(s\) 支队伍和第tt支队伍之间将有一场比赛,注意两只队间可能有多场比赛。

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

对于20%的数据\(2 \le n \le 10,0 \le m \le 20\)
对于100%的数据\(2 \le n \le 5000,0 \le m \le 1000,0 \le D_i \le C_i \le 10,0 \le a_i,b_i \le 50\)

analysis

  • 假设每场比赛两队都是 负,算出初始收益;
  • 考虑每场比赛,其中一队 胜;
    • \(源点s\)\(这场比赛i\) 连容量 1,费用 0 的边;
    • 然后考虑费用的增量:多赢一场比赛产生的收益。即 \((C*(w+1)^2+D*(l-1)^2)-(C*w^2+D*l^2)=2w*C-2l*D+C+D\)
      • 对于某支球队,假设后 \(M\) 场中其参加 \(x\) 场,那么最初 \(w=win,l=lose+x\),之后每赢一场 \(w++,l–~–\)
      • 我们从 \(这支球队\)\(汇点t\)\(x\) 条边,分别代表其赢了 \(j\) 场比赛时相对赢 \(j-1\) 场时收益的增量。
      • 由于增量递增,所以可以保证正确性。
  • \(ans=\) 所有队伍最初收益 \(+\) 最小费用最大流费用。
  • 数组的范围要考虑清楚,否则收获意想不到的评测结果。

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=5010,maxm=6010,maxe=1e5+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

char Out[1<<24],*fe=Out;
inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
template<typename T>inline void write(T x)
{
    if (!x) *fe++=48;
    if (x<0) *fe++='-', x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) *fe++=ch[num--];
    *fe++='\n';
}

int ver[maxe],edge[maxe],Next[maxe],cost[maxe],head[maxm],len=1;
inline void add(int x,int y,int z,int c)
{
    ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxm];
bool vis[maxm];
inline bool spfa()
{
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>q;q.push(s);
    dist[s]=0,vis[s]=1;
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x]; i; i=Next[i])
        {
            if (!edge[i]) continue;
            int y=ver[i];
            if (dist[y]>dist[x]+cost[i])
            {
                dist[y]=dist[x]+cost[i];
                if (!vis[y]) q.push(y),vis[y]=1;
            }
        }
    }
    if (dist[t]==inf) return false;
    else return true;
}

int ans;
inline int get(int x,int low)
{
    vis[x]=1;
    if (x==t) return low;
    int tmp=low;
    for (int i=head[x]; i; i=Next[i])
    {
        int y=ver[i];
        if (edge[i] && dist[y]==dist[x]+cost[i] && (!vis[y] || y==t))
        {
            int a=get(y,min(tmp,edge[i]));
            if (a>0)
            {
                ans+=a*cost[i];
                edge[i]-=a;
                edge[i^1]+=a;
                if (!(tmp-=a)) break;
            }
        }
    }
    return low-tmp;
}

inline void NetFlow()
{
    while (spfa())
    {
        vis[t]=1;
        while (vis[t])
        {
            memset(vis,0,sizeof(vis));
            get(s,inf);
        }
    }
}

typedef int iarr[maxn];
iarr win,lose,c,d,In;
int main()
{
    int n,m;read(n);read(m);
    s=0,t=n+m+1;
    for (int i=1; i<=n; ++i) read(win[i]),read(lose[i]),read(c[i]),read(d[i]);
    for (int i=1,x,y; i<=m; ++i) add(s,i,1,0),read(x),read(y),add(i,x+m,1,0),add(i,y+m,1,0),++In[x],++In[y];
    for (int i=1; i<=n; ++i) lose[i]+=In[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<=n; ++i)
        for (int j=1; j<=In[i]; ++j) add(i+m,t,1,2*c[i]*win[i]+c[i]+d[i]-2*d[i]*lose[i]),--lose[i],++win[i];
    NetFlow();
    write(ans);
    flush();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/G-hsm/p/11318051.html