【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。

因为费用的改变是包含平方的,所以我们需要拆边来做。

第i支队伍向T连fi条边,容量均为1,第j条边表示赢j场比赢j-1场多出来的收益,所以费用应为ci*(wi+j)^2+di*(wi+fi-j)^2-ci*(li+j-1)^2-di*(li+j+1)^2。

这里为了方便,直接把fi加到了li中。

然后跑最小费用最大流,加上之前的初始收益即为答案。

#include <cstdio>
#include <cstring>
#include <queue>
#define N 10010
#define M 3500000
using namespace std;
queue<int> q;
int w[N] , l[N] , c[N] , d[N] , x[N] , y[N] , f[N];
int head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N];
void add(int x , int y , int v , int c)
{
	to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
	to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
	int x , i;
	memset(from , -1 , sizeof(from));
	memset(dis , 0x3f , sizeof(dis));
	dis[s] = 0 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop();
		for(i = head[x] ; i ; i = next[i])
			if(val[i] && dis[to[i]] > dis[x] + cost[i])
				dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
	}
	return ~from[t];
}
int mincost()
{
	int i , k , ans = 0;
	while(spfa())
	{
		k = 0x7fffffff;
		for(i = t ; i != s ; i = from[i]) k = min(k , val[pre[i]]);
		ans += k * dis[t];
		for(i = t ; i != s ; i = from[i]) val[pre[i]] -= k , val[pre[i] ^ 1] += k;
	}
	return ans;
}
int main()
{
	int n , m , i , j , ans = 0;
	scanf("%d%d" , &n , &m) , s = 0 , t = m + n + 1;
	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%d%d" , &w[i] , &l[i] , &c[i] , &d[i]);
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x[i] , &y[i]) , f[x[i]] ++ , f[y[i]] ++ , l[x[i]] ++ , l[y[i]] ++ ;
	for(i = 1 ; i <= n ; i ++ ) ans += c[i] * w[i] * w[i] + d[i] * l[i] * l[i];
	for(i = 1 ; i <= m ; i ++ ) add(s , i , 1 , 0) , add(i , x[i] + m , 1 , 0) , add(i , y[i] + m , 1 , 0);
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= f[i] ; j ++ )
			add(i + m , t , 1 , c[i] * (2 * w[i] + 2 * j - 1) - d[i] * (2 * l[i] - 2 * j + 1));
	printf("%d\n" , ans + mincost());
	return 0;
}
时间: 2024-10-01 02:22:08

【bzoj1449/bzoj2895】[JSOI2009]球队收益/球队预算 费用流的相关文章

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

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1449 题意: 思路:首先,我们假设后面的M场比赛两方都是输的,即初始时的lose[i]再加上i参加的场次.这样,后面对于i,每赢一场的收益增加值为: 之后win[i]++,lose[i]--.至此,我们得到建图的方法: (1)源点到每场比赛连流量1,费用0: (2)每场比赛向双方连流量1,费用0: (3)每个人到汇点连x条边(x为该人在M场比赛中出现的次数),流量1,费用为上面计算出的

【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行每

【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&amp;&amp;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场比赛要进行. 问联盟

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

【题解】JSOI2009球队收益 / 球队预算

为什么大家都不写把输的场次增加的呢?我一定要让大家知道,这并没有什么关系~所以 \(C[i] <= D[i]\) 的条件就是来卖萌哒?? #include <bits/stdc++.h> using namespace std; #define maxn 1000000 #define INF 99999999 int n, m, S, T, rec[maxn], flow[maxn], a[maxn], b[maxn]; int ans, tot, c[maxn], d[maxn],

bzoj 1449 [JSOI2009]球队收益(费用拆分,最小费用流)

1449: [JSOI2009]球队收益 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 547  Solved: 302[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 [思路] 费用拆分,

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 orz huzecong 神犇的想法果然与众不同 首先看上去像网络流.这样就够了 先假设每场比赛两队都是输的,那么接下来转换的时候只要把其中一对变成赢的就好了. 考虑一支球队已经赢了x场输了y场现在要把输的y场之一变成赢的,考虑这样对答案的影响 原来是C[i]*

BZOJ 1449: [JSOI2009]球队收益( 最小费用最大流)

先考虑假如全部输了的收益. 再考虑每场比赛球队赢了所得收益的增加量,用这个来建图.. -------------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<iostre