热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:bzoj1449/bzoj2895[JSOI2009]球队收益/球队预算费用流

篇首语:本文由编程笔记#小编为大家整理,主要介绍了bzoj1449/bzoj2895[JSOI2009]球队收益/球队预算费用流相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了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
#include
#include
#define N 10010
#define M 3500000
using namespace std;
queue 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;
}

 

 


推荐阅读
author-avatar
手机用户2502895987
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有