BZOJ2895: 球队预算

【传送门:BZOJ2895


简要题意:

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


题解:

  费用流

  同BZOJ1449


参考代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
    int x,y,c,d,next,other;
    int el;
    node()
    {
        d=0;
    }
}a[110000];int len,last[6100];
void ins(int x,int y,int c,int d)
{
    int k1=++len,k2=++len;
    a[k1].x=x;a[k1].y=y;a[k1].c=c;a[k1].d=d;
    a[k1].next=last[x];last[x]=k1;
    a[k2].x=y;a[k2].y=x;a[k2].c=0;a[k2].d=-d;
    a[k2].next=last[y];last[y]=k2;
    a[k1].other=k2;
    a[k2].other=k1;
}
int st,ed;
int list[6100];
int d[6100];
bool v[6100];
int ans;
int pos[6100],pre[6100];
bool spfa()
{
    for(int i=st;i<=ed;i++) d[i]=999999999;
    d[st]=0;
    memset(v,false,sizeof(v));
    v[st]=true;
    int head=1,tail=2;
    list[1]=st;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(a[k].c>0&&d[y]>d[x]+a[k].d)
            {
                d[y]=d[x]+a[k].d;
                pos[y]=x;
                pre[y]=k;
                if(v[y]==false)
                {
                    v[y]=true;
                    list[tail++]=y;
                }
            }
        }
        head++;
        v[x]=false;
    }
    if(d[ed]==999999999) return false;
    else return true;
}
int w[5100],l[5100],C[5100],D[5100];
void Flow()
{
    while(spfa())
    {
        ans+=d[ed];
        for(int x=ed;x!=st;x=pos[x])
        {
            a[pre[x]].c--;
            a[a[pre[x]].other].c++;
        }
    }
}
int s[5100];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d%d%d",&w[i],&l[i],&C[i],&D[i]);
    int sum=0;
    st=0;ed=m+n+1;
    memset(s,0,sizeof(s));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        s[x]++;s[y]++;
        ins(st,i,1,0);
        ins(i,x+m,1,0);
        ins(i,y+m,1,0);
        l[x]++;l[y]++;
    }
    for(int i=1;i<=n;i++) ans+=C[i]*w[i]*w[i]+D[i]*l[i]*l[i];
    //C[i]*2*w[i]+C[i]-D[i]*2*l[i]+D[i]
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=s[i];j++)
        {
            ins(i+m,ed,1,C[i]*2*w[i]+C[i]-D[i]*2*l[i]+D[i]);
            w[i]++;l[i]--;
        }
    }
    Flow();
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-03-09 21:20  Star_Feel  阅读(140)  评论(0编辑  收藏  举报