• bzoj1449: [JSOI2009]球队收益


    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

     
    题解:
    这道题可以像wc2007石头剪刀布那样由S向每场比赛连一条容量为1费用为0的边,由每场比赛向两个人分别连容量为1费用为0的边
    现在要处理每个人如何向T连边
    假设i号队伍赢了x场输了y场,假如将i号队输了的某局改为i号队赢了,那么收益变化了c(x+1)2+d(y-1)2-cx2-dy2=2cx-2dy+c+d
    设i号队将要参加的比赛数为rest[i]
    我们先假设i队未确定的比赛都输了,那么由i号队向T连rest条边,容量均为1,费用分别为 2c*win[i]-2d*(lose[i]+rest[i])+c+d , 2c*(win[i]+1)-2d*(lose[i]+rest[i]-1)+c+d , ... , 2c*(win[i]+rest[i])-2d*lose[i]+c+d
    答案就是初始收益(假设了未确定的比赛都输了)+ 最小费用最大流的费用
    code:
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 6005
     7 #define maxm 20000
     8 #define inf 1061109567
     9 using namespace std;
    10 char ch;
    11 bool ok;
    12 void read(int &x){
    13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    14     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    15     if (ok) x=-x;
    16 }
    17 int n,m,a[1005],b[1005],ans,win[5005],lose[5005],rest[5005],c[5005],d[5005];
    18 struct costflow{
    19     int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm],cost[maxm];
    20     int dis[maxn],head,tail,list[maxn],tmp,totflow,totcost;
    21     bool bo[maxn];
    22     void init(){s=0,t=n+m+1,tot=1,memset(now,0,sizeof(now));}
    23     void put(int a,int b,int c,int d){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c,cost[tot]=d;}
    24     void add(int a,int b,int c,int d){put(a,b,c,d),put(b,a,0,-d);}
    25     void spfa(){
    26         memset(bo,0,sizeof(bo));
    27         memset(dis,63,sizeof(dis));
    28         head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
    29         while (head<tail){
    30             if (++head==maxn) head=1;
    31             int u=list[head];
    32             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
    33                 if (val[p]&&dis[v]>dis[u]+cost[p]){
    34                     dis[v]=dis[u]+cost[p];
    35                     if (!bo[v]){
    36                         if (++tail==maxn) tail=1;
    37                         list[tail]=v,bo[v]=1;
    38                     }
    39                 }
    40             bo[u]=0;
    41         }
    42     }
    43     int dfs(int u,int rest,int totval){
    44         bo[u]=1;
    45         if (u==t){totcost+=rest*totval;return rest;}
    46         int ans=0;
    47         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
    48             if (val[p]&&!bo[v]&&dis[v]==dis[u]+cost[p]){
    49                 int d=dfs(v,min(rest,val[p]),totval+cost[p]);
    50                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
    51             }
    52         return ans;
    53     }
    54     bool relax(){
    55         int d=inf;
    56         for (int u=s;u<=t;u++) if (bo[u])
    57             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
    58                 if (val[p]&&!bo[v]) d=min(d,dis[u]+cost[p]-dis[v]);
    59         if (d==inf) return false;
    60         for (int u=s;u<=t;u++) if (!bo[u]) dis[u]+=d;
    61         return true;
    62     }
    63     void work(){
    64         spfa(),totflow=totcost=0;
    65         do{
    66             do{
    67                 memset(bo,0,sizeof(bo));
    68                 tmp=dfs(s,inf,0),totflow+=tmp;
    69             }while (tmp);
    70         }while (relax());
    71     }
    72 }f;
    73 int main(){
    74     read(n),read(m),f.init();
    75     for (int i=1;i<=n;i++) read(win[i]),read(lose[i]),read(c[i]),read(d[i]);
    76     for (int i=1;i<=m;i++) read(a[i]),read(b[i]),rest[a[i]]++,rest[b[i]]++;
    77     for (int i=1;i<=n;i++){
    78         for (int x=win[i],y=lose[i]+rest[i];y>lose[i];x++,y--) 
    79             f.add(i,f.t,1,(c[i]<<1)*x-(d[i]<<1)*y+c[i]+d[i]);
    80         lose[i]+=rest[i],ans+=c[i]*win[i]*win[i]+d[i]*lose[i]*lose[i];
    81     }
    82     for (int i=1;i<=m;i++) f.add(f.s,n+i,1,0),f.add(n+i,a[i],1,0),f.add(n+i,b[i],1,0);
    83     f.work();
    84     printf("%d
    ",ans+f.totcost);
    85     return 0;
    86 }
  • 相关阅读:
    基于k8s搭建微服务日志收集中心
    分析java堆内存满时那些类占用内存居多
    yizimi 在 DMG 的板子库 (数据结构与算法)
    Contest 3/14
    基础算法训练1
    图论基础训练
    2021.03.09随笔
    树莓派 4B 安装 openEuler
    Docker 学习准备
    关于备案第二个服务器时遇到的问题
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5143446.html
Copyright © 2020-2023  润新知