博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 1449 JSOI2009 球队收益 费用流
阅读量:5748 次
发布时间:2019-06-18

本文共 2731 字,大约阅读时间需要 9 分钟。

题目大意:给定n支球队。第i支球队已经赢了wini场。输了losei场,接下来还有m场比赛。每一个球队终于的收益为Cix2i+Diy2i,当中xi为终于的胜场,yi为终于的负场

求最小化收益

考虑一仅仅球队,其收益与在接下来的比赛中的胜场数关系为:

0Ciwin2i+Di(di+losei)2
1Ci(wini+1)2+Di(di+losei1)2
2Ci(wini+2)2+Di(di+losei2)2
diCi(wini+di)2+Dilose2i

差分后可得:

赢第1Ci(2wini+1)Di[2(di+losei)1]
赢第2Ci(2wini+3)Di[2(di+losei)3]
赢第diCi[2wini+(2di1)]Di[2(di+losei)(2di1)]

easy发现差分后单调递增。故收益是关于胜场数的一个下凸函数,能够拆边做

于是我们将每支球队和每场比赛都变成一个点,建图跑费用流

源点向第i个点连di条边。流量为1。第j条边的费用为Ci[2wini+(2j1)]Di[2(di+losei)(2j1)]

每场比赛的两方向这场比赛连一条流量为1费用为0的边
每场比赛向汇点连一条流量为1费用为0的边

最小费用+ni=1[Ciwin2i+Di(di+losei)2]就是答案

#include 
#include
#include
#include
#define M 6060#define S 0#define T (M-1)#define INF 0x3f3f3f3fusing namespace std;int n,m,ans;int win[M],lose[M],C[M],D[M],d[M];namespace Min_Cost_Max_Flow{ struct abcd{ int to,flow,cost,next; }table[1001001]; int head[M],tot=1; void Add(int x,int y,int f,int c) { table[++tot].to=y; table[tot].flow=f; table[tot].cost=c; table[tot].next=head[x]; head[x]=tot; } void Link(int x,int y,int f,int c) { Add(x,y,f,c); Add(y,x,0,-c); } bool Edmonds_Karp() { static int q[65540],cost[M],flow[M],from[M]; static unsigned short r,h; static bool v[M]; int i; memset(cost,0x3f,sizeof cost); cost[S]=0;flow[S]=INF;q[++r]=S; while(r!=h) { int x=q[++h];v[x]=false; for(i=head[x];i;i=table[i].next) if(table[i].flow&&cost[table[i].to]>cost[x]+table[i].cost) { cost[table[i].to]=cost[x]+table[i].cost; flow[table[i].to]=min(flow[x],table[i].flow); from[table[i].to]=i; if(!v[table[i].to]) v[table[i].to]=true,q[++r]=table[i].to; } } if(cost[T]==0x3f3f3f3f) return false; ans+=cost[T]*flow[T]; for(i=from[T];i;i=from[table[i^1].to]) table[i].flow-=flow[T],table[i^1].flow+=flow[T]; return true; }}int main(){ using namespace Min_Cost_Max_Flow; int i,j,x,y; cin>>n>>m; for(i=1;i<=n;i++) scanf("%d%d%d%d",&win[i],&lose[i],&C[i],&D[i]); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); Link(x,n+i,1,0); Link(y,n+i,1,0); Link(n+i,T,1,0); d[x]++;d[y]++; } for(i=1;i<=n;i++) { ans+=C[i]*win[i]*win[i]+D[i]*(d[i]+lose[i])*(d[i]+lose[i]); for(j=1;j<=d[i];j++) Link(S,i,1, C[i]*(2*win[i]+j*2-1)-D[i]*(2*(d[i]+lose[i])-j*2+1) ); } while( Edmonds_Karp() ); cout<
<

转载地址:http://knhzx.baihongyu.com/

你可能感兴趣的文章
排序高级之交换排序_冒泡排序
查看>>
Cocos2d-x3.2 Ease加速度
查看>>
[EntLib]关于SR.Strings的使用办法[加了下载地址]
查看>>
中小型网站架构分析及优化
查看>>
写shell的事情
查看>>
负载均衡之Haproxy配置详解(及httpd配置)
查看>>
linux虚拟机拷贝之后联网出错
查看>>
Linux文件系统探索
查看>>
标准与扩展ACL 、 命名ACL 、 总结和答疑
查看>>
查找恶意的TOR中继节点
查看>>
MAVEN 属性定义与使用
查看>>
shell高级视频答学生while循环问题
查看>>
使用@media实现IE hack的方法
查看>>
《11招玩转网络安全》之第一招:Docker For Docker
查看>>
hive_0.11中文用户手册
查看>>
hiveserver2修改线程数
查看>>
XML教程
查看>>
oracle体系结构
查看>>
Microsoft Exchange Server 2010与Office 365混合部署升级到Exchange Server 2016混合部署汇总...
查看>>
Proxy服务器配置_Squid
查看>>