zoukankan      html  css  js  c++  java
  • BZOJ 1449 JSOI2009 球队收益 费用流

    题目大意:给定n支球队。第i支球队已经赢了wini场。输了losei场,接下来还有m场比赛。每一个球队终于的收益为Cix2i+Diy2i,当中xi为终于的胜场,yi为终于的负场
    求最小化收益

    考虑一仅仅球队,其收益与在接下来的比赛中的胜场数关系为:
    0Ciwin2i+Di(di+losei)2
    1Ci(wini+1)2+Di(di+losei1)2
    2Ci(wini+2)2+Di(di+losei2)2

    diCi(wini+di)2+Dilose2i

    差分后可得:
    赢第1Ci(2wini+1)Di[2(di+losei)1]
    赢第2Ci(2wini+3)Di[2(di+losei)3]

    赢第diCi[2wini+(2di1)]Di[2(di+losei)(2di1)]

    easy发现差分后单调递增。故收益是关于胜场数的一个下凸函数,能够拆边做

    于是我们将每支球队和每场比赛都变成一个点,建图跑费用流

    源点向第i个点连di条边。流量为1。第j条边的费用为Ci[2wini+(2j1)]Di[2(di+losei)(2j1)]
    每场比赛的两方向这场比赛连一条流量为1费用为0的边
    每场比赛向汇点连一条流量为1费用为0的边

    最小费用+ni=1[Ciwin2i+Di(di+losei)2]就是答案

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define M 6060
    #define S 0
    #define T (M-1)
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m,ans;
    int win[M],lose[M],C[M],D[M],d[M];
    namespace Min_Cost_Max_Flow{
        struct abcd{
            int to,flow,cost,next;
        }table[1001001];
        int head[M],tot=1;
        void Add(int x,int y,int f,int c)
        {
            table[++tot].to=y;
            table[tot].flow=f;
            table[tot].cost=c;
            table[tot].next=head[x];
            head[x]=tot;
        }
        void Link(int x,int y,int f,int c)
        {
            Add(x,y,f,c);
            Add(y,x,0,-c);
        }
        bool Edmonds_Karp()
        {
            static int q[65540],cost[M],flow[M],from[M];
            static unsigned short r,h;
            static bool v[M];
            int i;
            memset(cost,0x3f,sizeof cost);
            cost[S]=0;flow[S]=INF;q[++r]=S;
            while(r!=h)
            {
                int x=q[++h];v[x]=false;
                for(i=head[x];i;i=table[i].next)
                    if(table[i].flow&&cost[table[i].to]>cost[x]+table[i].cost)
                    {
                        cost[table[i].to]=cost[x]+table[i].cost;
                        flow[table[i].to]=min(flow[x],table[i].flow);
                        from[table[i].to]=i;
                        if(!v[table[i].to])
                            v[table[i].to]=true,q[++r]=table[i].to;
                    }
            }
            if(cost[T]==0x3f3f3f3f) return false;
            ans+=cost[T]*flow[T];
            for(i=from[T];i;i=from[table[i^1].to])
                table[i].flow-=flow[T],table[i^1].flow+=flow[T];
            return true;
        }
    }
    int main()
    {
        using namespace Min_Cost_Max_Flow;
        int i,j,x,y;
        cin>>n>>m;
        for(i=1;i<=n;i++)
            scanf("%d%d%d%d",&win[i],&lose[i],&C[i],&D[i]);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            Link(x,n+i,1,0);
            Link(y,n+i,1,0);
            Link(n+i,T,1,0);
            d[x]++;d[y]++;
        }
        for(i=1;i<=n;i++)
        {
            ans+=C[i]*win[i]*win[i]+D[i]*(d[i]+lose[i])*(d[i]+lose[i]);
            for(j=1;j<=d[i];j++)
                Link(S,i,1, C[i]*(2*win[i]+j*2-1)-D[i]*(2*(d[i]+lose[i])-j*2+1) );
        }
        while( Edmonds_Karp() );
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    mybatis入门
    windows环境下搭建RocketMQ
    主键-雪花算法
    Springboot杂七杂八
    springboot整合webSocket的使用
    sss
    sss
    sss
    sss
    sss
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5082132.html
Copyright © 2011-2022 走看看