• bzoj1449/2895: [JSOI2009]球队收益(最小费用最大流)


    www.cnblogs.com/shaokele/


    bzoj1449: [JSOI2009]球队收益##

      Time Limit: 5 Sec
      Memory Limit: 64 MB

    Description###

      p1
     

    Input###

      p2
     

    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

      p3
      

    题目地址:  bzoj1449: [JSOI2009]球队收益

    题目大意:   题目很简洁了:)####

      

    题解:   hzwer

      最小费用最大流
      
      首先假设每场比赛两队都是负......算出初始收益
      
      然后考虑每次比赛,其中一队为胜
      
      从源向每场比赛连流量1费用0的边,从比赛向这场比赛的两支队都连一条流量1费用0的边
      
      然后考虑费用的增量:多赢一场比赛产生的收益。即 $$(C(w+1)2+D*(l-1)2)-(Cw2+D*l2)=2wC-2lD+C+D$$
      
      对于某支球队,假设后M场中其参加x场,那么最初 (w=win,l=lose+x) ,之后每赢一场 (w++,l--)
      
      我们从它向汇连 (x) 条边,分别代表其赢了 (j) 场比赛时相对赢 (j-1) 场时收益的增量。由于增量递增,所以可以保证正确性。
      
      答案为所有队伍最初收益+最小费用最大流费用。
      


    AC代码

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=5005,M=1005,inf=1e9;
    int n,m,S,T,cnt,ans;
    int last[N+M],q[N+M],d[N+M],from[N+M];
    int win[N],lose[N],C[N],D[N],s[N];
    bool inq[N+M];
    struct edge{
        int from,to,v,c,next;
    }e[100005];
    void insert(int u,int v,int w,int c){
        e[++cnt]=(edge){u,v,w,c,last[u]};last[u]=cnt;
        e[++cnt]=(edge){v,u,0,-c,last[v]};last[v]=cnt;
    }
    bool spfa(){
        for(int i=S;i<=T;i++)d[i]=inf;
        int l=0,r=1;q[0]=S;
        d[S]=0;inq[S]=1;
        while(l!=r){
            int u=q[l++];if(l==T)l=0;
            for(int i=last[u];i;i=e[i].next)
                if(e[i].v && d[e[i].to]>d[u]+e[i].c){
                    d[e[i].to]=d[u]+e[i].c;
                    from[e[i].to]=i;
                    if(!inq[e[i].to]){
                        inq[e[i].to]=1;
                        q[r++]=e[i].to;
                        if(r==T)r=0;
                    }
                }
            inq[u]=0;
        }
        if(d[T]==inf)return 0;
        return 1;
    }
    void mcf(){
        int x=inf;
        for(int i=from[T];i;i=from[e[i].from])
            x=min(x,e[i].v);
        for(int i=from[T];i;i=from[e[i].from]){
            e[i].v-=x;
            e[i^1].v+=x;
            ans+=e[i].c*x;
        }
    }
    int main(){
        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]);
        S=0;T=n+m+1;cnt=1;
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            insert(S,i,1,0);
            insert(i,m+u,1,0);
            insert(i,m+v,1,0);
            s[u]++;s[v]++;
        }
        for(int i=1;i<=n;i++){
            lose[i]+=s[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<=s[i];j++){
                insert(m+i,T,1,2*C[i]*win[i]+C[i]+D[i]-2*D[i]*lose[i]);
                lose[i]--;win[i]++;
            }
        while(spfa())mcf();
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    MS SQL Server获取月份名称缩写
    视频站点程序
    视频站点程序 Ver2
    Infor Syteline 数据库增长月报表
    判断是否有选择RadioButtonList
    获取用户控件中控件的ID
    FileUpload上传图片前首先预览一下
    为TextBox装饰水印
    导航条的重构
    用户自己排序记录
  • 原文地址:https://www.cnblogs.com/shaokele/p/9118368.html
Copyright © 2020-2023  润新知