[bzoj 1449] 球队收益(费用流)


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


Solution

这题费用流裸题好吧。

先假设所有队在接下来的比赛中都会输掉,算出收益。

但是一场比赛应该有且只有一支球队赢得比赛,所以真实收益和我们算出来的收益就会有一些差值,再计算最小的差值即可。

我们可以发现,队伍\(i\)每赢得一场比赛,就会多获得\(C_i * (2 * Win_i + 1) - D_i * (2 * Lost_i - 1)\) 的收益,并且由于赢得越多,\(Win_i\)就会越大,\(Lost_i\)就会越小,所以获得的收益差值就会越来越大。 于是我们可以建立一个最小费用最大流的模型。

  1. 我们建立一个源点,向所有比赛建一条流量为1,费用为0的边。
  2. 从比赛向其两支球队建立一条流量为1,费用为0的边。
  3. 从每支球队向汇点建x(x是该支球队参加的比赛数)条边,每条边流量为1,费用每赢一场的差值。

PS: 这里要注意一点,差值会随着赢的场数增多而增多,所以最小费用最大流一定会先走赢第一场,再走第二场,第三场,等等。。。这是算法正确性的关键。

建好图,然后跑一遍最小费用最大流,加上之前的答案,这题就完了。

Code

  1. #include <cstdio>
  2. #include <queue>
  3. #include <iostream>
  4. using namespace std;
  5. const int maxn = 5e3 + 10, maxm = 1e3 + 10, inf = 1e9 + 7;
  6. int n, m, S, T, cnt;
  7. int w[maxn], l[maxn], a[maxn], b[maxn], x[maxn];
  8. int dis[maxn+maxm], inq[maxn+maxm];
  9. queue<int> q;
  10. struct edge {int u, v, f, c; edge *next, *rev;} e[maxn<<1], *head[maxn+maxm], *from[maxn+maxm];
  11. inline void adde(int u, int v, int flow, int cost) {
  12. e[cnt] = (edge){u, v, flow, cost, head[u], &e[cnt+1]}, head[u] = &e[cnt++];
  13. e[cnt] = (edge){v, u, 0, -cost, head[v], &e[cnt-1]}, head[v] = &e[cnt++];
  14. }
  15. bool spfa() {
  16. while(!q.empty()) q.pop();
  17. for(int i = 1; i <= m + n + 1; i++) dis[i] = inf, inq[i] = 0, from[i] = NULL;
  18. dis[S] = 0, inq[S] = 1; q.push(S);
  19. while(!q.empty()) {
  20. int u = q.front(); q.pop(), inq[u] = 0;
  21. for(edge *k = head[u]; k; k = k->next) if(k->f) {
  22. if(dis[k->v] > dis[u] + k->c) {
  23. dis[k->v] = dis[u] + k->c;
  24. from[k->v] = k;
  25. if(!inq[k->v]) inq[k->v] = 1, q.push(k->v);
  26. }
  27. }
  28. }
  29. return dis[T] != inf;
  30. }
  31. int mcf() {
  32. int res = 0, xx = inf;
  33. for(edge *k = from[T]; k; k = from[k->u]) xx = min(xx, k->f);
  34. for(edge *k = from[T]; k; k = from[k->u])
  35. res += xx * k->c, k->f -= xx, k->rev->f += xx;
  36. return res;
  37. }
  38. int main() {
  39. int u, v;
  40. scanf("%d%d", &n, &m);S = 0, T = n + m + 1;
  41. for(int i = 1; i <= n; i++) scanf("%d%d%d%d", w+i, l+i, a+i, b+i);
  42. for(int i = 1; i <= m; i++) {
  43. scanf("%d%d", &u, &v);
  44. l[u]++, l[v]++;
  45. x[u]++, x[v]++;
  46. adde(S, n+i, 1, 0);
  47. adde(n + i, u, 1, 0);
  48. adde(n + i, v, 1, 0);
  49. }
  50. int ans = 0;
  51. for(int i = 1; i <= n; i++) {
  52. ans += w[i] * w[i] * a[i] + l[i] * l[i] * b[i];
  53. for(int j = 0; j < x[i]; j++)
  54. adde(i, T, 1, a[i]*(2*w[i]+1) - b[i] * (2 * l[i] - 1)),
  55. w[i]++, l[i]--;
  56. }
  57. while(spfa()) ans += mcf();
  58. printf("%d\n", ans);
  59. return 0;
  60. }

[bzoj 1449] 球队收益(费用流)的更多相关文章

  1. BZOJ 1449 JSOI2009 球队收益 费用流

    题目大意:给定nn支球队.第ii支球队已经赢了winiwin_i场.输了loseilose_i场,接下来还有mm场比赛.每一个球队终于的收益为Ci∗x2i+Di∗y2iC_i*x_i^2+D_i*y_ ...

  2. BZOJ 1449 球队收益(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1449 题意: 思路:首先,我们假设后面的M场比赛两方都是输的,即初始时的lose[i]再 ...

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

    题目描述 输入 输出 一个整数表示联盟里所有球队收益之和的最小值. 样例输入 3 3 1 0 2 1 1 1 10 1 0 1 3 3 1 2 2 3 3 1 样例输出 43 题解 费用流 由于存在一 ...

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

    球队预算 Time Limit: 10 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 在一个篮球联赛里,有n支球队, 球 ...

  5. BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)

    BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...

  6. bzoj 1070: [SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2785  Solved: 1110[Submit][Status] ...

  7. BZOJ 3171 循环格(费用流)

    题意 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走.即如果(r ...

  8. BZOJ 1070 修车 【费用流】

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...

  9. BZOJ 1930 吃豆豆(费用流)

    首先这题的两条线不相交的限制可以去掉,因为如果相交的话把点换一换是不影响最终结果的. 剩下的费用流建图是显然的,把点拆为两个,建立超级源点s和源点ss汇点t,连边(s,ss,2,0). 对于每个点,连 ...

随机推荐

  1. est6 -- Object.is()、Object.assign()、Object.defineProperty()、Symbol、Proxy

    Object.is()用来比较两个值是否严格相等.它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身. + === - //true NaN === ...

  2. Java 添加播放MIDI音乐

      Java 在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐. 如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了. 网上很多播放MIDI的教程都是 ...

  3. Spring配置项之<aop:aspectj-autoproxy />

    通过配置织入@Aspectj切面 虽然可以通过编程的方式织入切面,但是一般情况下,我们还是使用spring的配置自动完成创建代理织入切面的工作. 通过aop命名空间的<aop:aspectj-a ...

  4. IntelliJ IDEA版本:Ultimate、Community、EAP版本的区别

    Community: 社区版,免费,但是功能有限制,Android Studio就是基于这个版本定制的. http://idea-intellij.com/intellij-community/ Ul ...

  5. Java中HashMap的初始容量设置

    根据阿里巴巴Java开发手册上建议HashMap初始化时设置已知的大小,如果不超过16个,那么设置成默认大小16: 集合初始化时, 指定集合初始值大小. 说明: HashMap使用HashMap(in ...

  6. SQL Server 2008 镜像的监控 - Joe.TJ -

    http://www.cnblogs.com/Joe-T/archive/2012/09/06/2673237.html

  7. javascript 函数初探 (五)--- 几种类型的函数

    即时函数: 目前我们已经讨论了匿名函数在回调时的应用.接下来,我们来看看匿名函数的另一种应用实例 --- javascript即时函数: 比如: ( function(){ alert('her'); ...

  8. GO -- socket读取内容

    func handleRead(conn net.Conn, done chan string) { for { buf := make([]) reqLen, err := conn.Read(bu ...

  9. 使用Cout输出String和CString对象

    CString和string都是一个类,不同的是CString主要用于MFC或者是ATL编程中,而string则多用于Windows控制台编程中 在实际编程过程中,我们经常用到string或者是CSt ...

  10. 如何获得(读取)web.xml配置文件的參数

    參考代码例如以下: com.atguigu.struts2.app.converters.DateConverter.java public DateFormat getDateFormat(){ i ...