【BZOJ1449&&2895】球队预算 [费用流]

球队预算

Time Limit: 10 Sec  Memory Limit: 256 MB
[Submit][Status][Discuss]

Description

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

Input

  第一行n,m

  接下来n行每行4个整数a[i],b[i],Ci,Di

  再接下来m行每行两个整数s,t表示第s支队伍和第t支队伍之间将有一场比赛,注意两只队间可能有多场比赛。

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

  2<=n<=5000,0<=m<=1000,0<=di<=ci<=10,0<=a[i],b[i]<=50.

Source

  这题很棒棒,肯定是个费用流。我们可以首先假设所有场次都是输的,然后每次调整赢的场次来获得最小答案。
  怎么建边呢?
    S->比赛 流量为1,费用为0 mean : 一场比赛
    比赛->两只队伍 流量为1,费用为0 mean : 流过去则表示这支队伍获得了胜利
    队伍->T 连若干条边,流量为1,费用为 C*(2a+1)-D*(2b-1) mean : 获胜得到的收益
    为什么呢?这个可以用平方关系得到(多赢一场,少输一场)
  然后用原来的答案+最小费用即可。

Code

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cmath>
  8 using namespace std;
  9 typedef long long s64;
 10
 11 const int ONE = 50001;
 12 const int EDG = 1000001;
 13 const int INF = 2147483640;
 14
 15 int n,m;
 16 int x,y;
 17 int S,T;
 18 int Num[ONE];
 19 int next[EDG],first[ONE],go[EDG],from[EDG],pas[EDG],w[EDG],tot;
 20 int dist[ONE],pre[ONE],vis[ONE];
 21 int tou,wei,q[ONE];
 22 int Ans;
 23
 24 struct power
 25 {
 26         int a,b,C,D;
 27 }A[ONE];
 28
 29 inline int get()
 30 {
 31         int res=1,Q=1;  char c;
 32         while( (c=getchar())<48 || c>57)
 33         if(c==‘-‘)Q=-1;
 34         if(Q) res=c-48;
 35         while((c=getchar())>=48 && c<=57)
 36         res=res*10+c-48;
 37         return res*Q;
 38 }
 39
 40 void Add(int u,int v,int flow,int z)
 41 {
 42         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  from[tot]=u;    pas[tot]=flow;  w[tot]=z;
 43         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;  from[tot]=v;    pas[tot]=0;     w[tot]=-z;
 44 }
 45
 46 bool Bfs()
 47 {
 48         for(int i=S;i<=T;i++) dist[i] = INF;
 49         dist[S] = 0;    vis[S] = 1;
 50         tou = 0; wei = 1; q[1] = S;
 51         while(tou < wei)
 52         {
 53             int u = q[++tou];
 54             for(int e=first[u]; e; e=next[e])
 55             {
 56                 int v = go[e];
 57                 if(dist[v] > dist[u] + w[e] && pas[e])
 58                 {
 59                     dist[v] = dist[u] + w[e]; pre[v] = e;
 60                     if(!vis[v])
 61                     {
 62                         vis[v] = 1;
 63                         q[++wei] = v;
 64                     }
 65                 }
 66             }
 67             vis[u] = 0;
 68         }
 69         return dist[T] != INF;
 70 }
 71
 72 void Deal()
 73 {
 74         int x = INF;
 75         for(int e=pre[T]; e; e=pre[from[e]]) x = min(x,pas[e]);
 76         for(int e=pre[T]; e; e=pre[from[e]])
 77         {
 78             pas[e] -= x;
 79             pas[((e-1)^1)+1] += x;
 80             Ans += x*w[e];
 81         }
 82 }
 83
 84 void Build()
 85 {
 86         S=0;    T=n+m+1;
 87         for(int i=1;i<=m;i++)
 88         {
 89             x=get();    y=get();
 90             Add(S,i, 1,0);
 91             Add(i,x+m, 1,0);    Add(i,y+m, 1,0);
 92
 93             Num[x]++;    Num[y]++;
 94             A[x].b++;    A[y].b++;
 95         }
 96
 97         for(int i=1;i<=n;i++)
 98         {
 99             Ans += A[i].a*A[i].a * A[i].C + A[i].b*A[i].b * A[i].D;
100             for(int j=1;j<=Num[i];j++)
101             {
102                 Add(i+m,T, 1,A[i].C*(2*A[i].a+1) - A[i].D*(2*A[i].b-1) );
103                 A[i].a++; A[i].b--;
104             }
105         }
106 }
107
108 int main()
109 {
110         n=get();    m=get();
111         for(int i=1;i<=n;i++)
112         {
113             A[i].a=get();    A[i].b=get();
114             A[i].C=get();    A[i].D=get();
115         }
116
117         Build();
118
119         while(Bfs()) Deal();
120
121         printf("%d",Ans);
122
123 }

时间: 2024-11-08 07:57:35

【BZOJ1449&&2895】球队预算 [费用流]的相关文章

bozj 1449/2895: 球队预算 -- 费用流

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

【bzoj1449/bzoj2895】[JSOI2009]球队收益/球队预算 费用流

题目描述 输入 输出 一个整数表示联盟里所有球队收益之和的最小值. 样例输入 3 3 1 0 2 1 1 1 10 1 0 1 3 3 1 2 2 3 3 1 样例输出 43 题解 费用流 由于存在一个赢一个输,比较难算.我们可以先假设它们都输掉,然后再安排赢的情况. 设fi为i还要打的比赛数目,那么初始的收益为∑ci*wi^2+di*(li+fi)^2. S->每场比赛,容量为1,费用为0. 每场比赛->比赛的两队,容量为1,费用为0. 因为费用的改变是包含平方的,所以我们需要拆边来做. 第

BZOJ 1449 JSOI2009 球队收益 费用流

题目大意:给定n支球队,第i支球队已经赢了wini场,输了losei场,接下来还有m场比赛,每个球队最终的收益为Ci?x2i+Di?y2i,其中xi为最终的胜场,yi为最终的负场 求最小化收益 考虑一只球队,其收益与在接下来的比赛中的胜场数关系为: 赢0场 Ci?win2i+Di?(di+losei)2 赢1场 Ci?(wini+1)2+Di?(di+losei?1)2 赢2场 Ci?(wini+2)2+Di?(di+losei?2)2 - 赢di场 Ci?(wini+di)2+Di?lose2

【BZOJ-1449&amp;2895】球队收益&amp;球队预算 最小费用最大流

1449: [JSOI2009]球队收益 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 648  Solved: 364[Submit][Status][Discuss] 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 Source 2895: 球队预算

【BZOJ1449/2895】[JSOI2009]球队收益/球队预算 最小费用最大流

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

【网络流24题】No.19 负载平衡问题 (费用流)

[题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input.txt517 9 14 16 4 输出文件示例output.txt11 [分析] 其实我觉得这题可以贪心啊..n^2贪心??.没细想.. 打的是费用流.. 大概这样建图: 懒得写了..凌乱之美.. 求满流费用.. 1 #include<cstdio> 2 #include<cstdlib&

POJ 3422 kaka&#39;s matrix trvals(费用流)

#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <cma

hdu 2448 Mining Station on the Sea【网络费用流】

Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2371    Accepted Submission(s): 732 Problem Description The ocean is a treasure house of resources and the development

POJ训练计划3422_Kaka&#39;s Matrix Travels(网络流/费用流)

解题报告 题目传送门 题意: 从n×n的矩阵的左上角走到右下角,每次只能向右和向下走,走到一个格子上加上格子的数,可以走k次.问最大的和是多少. 思路: 建图:每个格子掰成两个点,分别叫"出点","入点", 入点到出点间连一个容量1,费用为格子数的边,以及一个容量∞,费用0的边. 同时,一个格子的"出点"向它右.下的格子的"入点"连边,容量∞,费用0. 源点向(0,0)的入点连一个容量K的边,(N-1,N-1)的出点向汇点连一