【BZOJ-14492895】球队收益球队预算 最小费用最大流
1449: [JSOI2009]球队收益
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 648 Solved: 364
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1
Sample Output
HINT
Source
2895: 球队预算
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 51 Solved: 50
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1
Sample Output
Data Limit
对于20%的数据2<=n<=10,0<=m<=20
对于100%的数据2<=n<=5000,0<=m<=1000,0<=di<=ci<=10,0<=a[i],b[i]<=50.
HINT
Source
Solution
idea很好的建图,不能考虑直接建,而应该利用增量的思想
个人的想法是这样的:
源到各比赛连边,容量为1,费用为0
建每个球队分成两个,由个比赛连向两只球队a,b,再由a连b',b连a',分别表示a赢了这场比赛或b赢了这场比赛
然后由各个点i'连向汇容量为inf,费用为0
然后预处理出来已比完的比赛胜负的价值,加上最小费用即可;
思路是考虑一场比赛的胜负对于结果的贡献,从这场比赛结束后对结果的增量来考虑,但显然这种方法并不是很优,但理论上可A
那么同样的思想,换一种方法建图:
不妨先假设后面的M场比赛中双方都是输家,这样我们只要在模型中表示一方成为赢家即可。
此应该有一个初步的模型了:对于N支球队和M场比赛各建一个点,从源向每场比赛连流量1费用0的边,从比赛向参与这场比赛的两支队伍各连一条流量1费用0的边。剩下的就是队伍收益的费用表示了。
多赢一场比赛产生的收益。即(C*(w+1)^2+D*(l-1)^2)-(C*w^2+D*l^2)=2w*C-2l*D+C+D。对于第i支队伍,假设后M场中i参加的有x场,那么最初w=win,l=lose+x,之后每赢一场w++,l--。我们从第i支队伍的点向汇连x条边,分别代表第i支队伍赢了j场比赛时相对赢j-1场时收益的增量。由于增量一定越来越大(平方嘛),所以流量最先流过的一定是费用较小的边,即j最小的边。
-----by huzecong
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> using namespace std; int read() {int x=0,f=1; char ch=getchar();while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();}while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}return x*f; } #define maxn 5100+1100 #define maxm 100100 int n,m,ans,S,T,num[5010]; struct Teamnode{int win,lose,C,D;}team[5010]; struct Edgenode{int to,next,cap,cost,from;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w,int c) {cnt++;edge[cnt].from=u;edge[cnt].to=v; edge[cnt].next=head[u];head[u]=cnt; edge[cnt].cost=c;edge[cnt].cap=w;} void insert(int u,int v,int w,int c){add(u,v,w,c);add(v,u,0,-c);} #define inf 0x7fffffff int q[maxn],h,t; int dis[maxn];bool mark[maxn]; bool spfa() {memset(mark,0,sizeof(mark));for (int i=S; i<=T; i++) dis[i]=inf;h=0,t=1;q[0]=T; mark[T]=1; dis[T]=0;while (h<t){int now=q[h++]; mark[now]=0;for (int i=head[now]; i; i=edge[i].next)if (edge[i^1].cap && dis[now]+edge[i^1].cost<dis[edge[i].to]){ dis[edge[i].to]=dis[now]+edge[i^1].cost;if (!mark[edge[i].to])mark[edge[i].to]=1,q[t++]=edge[i].to;}}return dis[S]!=inf; } int dfs(int loc,int low) {mark[loc]=1;if (loc==T) return low;int w,used=0;for (int i=head[loc]; i; i=edge[i].next)if (!mark[edge[i].to] && edge[i].cap && dis[edge[i].to]==dis[loc]-edge[i].cost){w=dfs(edge[i].to,min(low-used,edge[i].cap));edge[i].cap-=w; edge[i^1].cap+=w;ans+=w*edge[i].cost; used+=w;if (used==low) return low;}return used; } int zkw() {int tmp=0;while (spfa()){mark[T]=1;while (mark[T]){memset(mark,0,sizeof(mark));tmp+=dfs(S,inf);}}return tmp; } int power(int x){return x*x;} void build() {S=0,T=n+m+1;for(int a,b,i=1; i<=m; i++)insert(S,i,1,0),a=read(),b=read(),insert(i,a+m,1,0),insert(i,b+m,1,0),num[a]++,num[b]++;for(int i=1; i<=n; i++)team[i].lose+=num[i];for(int i=1; i<=n; i++)ans+=power(team[i].win)*team[i].C+power(team[i].lose)*team[i].D;for(int i=1; i<=n; i++)for(int j=1;j<=num[i];j++)insert(i+m,T,1,2*team[i].C*team[i].win+team[i].C+team[i].D-2*team[i].D*team[i].lose),team[i].lose--,team[i].win++; } int main() {n=read(),m=read();for (int i=1; i<=n; i++)team[i].win=read(),team[i].lose=read(),team[i].C=read(),team[i].D=read();build();int Maxflow=zkw();printf("%d\n",ans);return 0; }
吐槽一句..增广的过程中,一开始使用STL中的queue然后莫名的WA了?手写了个q...怒A...跑得飞快
转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5354337.html
【BZOJ-14492895】球队收益球队预算 最小费用最大流相关推荐
- BZOJ1449[JSOI2009]球队收益BZOJ2895球队预算——最小费用最大流
题目描述 输入 输出 一个整数表示联盟里所有球队收益之和的最小值. 样例输入 3 3 1 0 2 1 1 1 10 1 0 1 3 3 1 2 2 3 3 1 样例输出 43 提示 要求总费用最低考虑 ...
- bzoj 2245 [SDOI2011]工作安排【最小费用最大流】
其实不用拆点,对于每个人我们假装他是\( s[i]+1 \)个点,可以由他向T点分别连\( s[i]+1 \)条边,容量为\( t[i][j]-t[i][j-1]\),由S点向所有产品i连容量为c[i ...
- bzoj 1061: [Noi2008]志愿者招募【最小费用最大流】
神奇的建图:连接(s,1,inf,0)(n+1,t,inf,0),对于1~n连接(i,i+1,inf-a[i],0),对于每个志愿者(s,t,c),连接(s,t+1,inf,c). 因为从s开始的流是 ...
- bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】
第一问直接跑最大流即可.建图的时候按照费用流建,费用为0. 对于第二问,在第一问dinic剩下的残量网络上建图,对原图的每条边(i,j),建(i,j,inf,cij),表示可以用c的花费增广这条路.然 ...
- BZOJ 1221: [HNOI2001] 软件开发(最小费用最大流)
不知道为什么这么慢.... 费用流,拆点.... --------------------------------------------------------------------------- ...
- bzoj 1070: [SCOI2007]修车【最小费用最大流】
一开始从客人角度想的,怎么建都不对 从一个修车工所接待的所有顾客花费的总时间来看,设一共有x个人,那么第一个修的对总时间的贡献是x*w1,第二个是(x-1)*w2-以此类推.所以把第i个修车工拆成n组 ...
- 有下界的最小费用可行流2.0(bzoj 3876: [Ahoi2014]支线剧情)
什么是有下界的最小费用可行流? 平时来讲都是最小费用最大流,也就是在满流的前提条件下费用尽可能的少,而最小费用可行流一般不要求满流,但是每条边都有最小流量要求(比如经过边e(u,v)的流量不能少于4等 ...
- BZOJ 1061 志愿者招募(最小费用最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...
- c语言最小费用流_策略算法工程师之路-图优化算法(一)(二分图amp;最小费用最大流)...
目录 1.图的基本定义 2.双边匹配问题 2.1 二分图基本概念 2.2 二分图最大匹配求解 2.3 二分图最优匹配求解 2.4 二分图最优匹配建模实例 2.4.1 二分图最优匹配在师生匹配中的应用 ...
最新文章
- mycat mysql 主从切换_Mycat读写分离与主从切换
- 【知识发现】基于物品的协同过滤推荐算法python实现
- 声学多普勒流速剖面仪_雷达流量计/流速仪厂家有哪些?
- 【Qt调试技巧】Profile配置使用及一些坑
- 判断文件是否改变php,PHP判断文件是否被修改实例
- Bootstrap3.0学习第十一轮(输入框组)
- Ubuntu系统(四)-修改主机名和配置DNS上网
- 解决问题:UserWarning: Matplotlib is currently using agg, which is a non-GUI backend.
- 【ZJCPC2019 第16届 浙江省赛】The 16th Zhejiang Provincial Collegiate Programming Contest(GFHIJ 5题)
- Configure universal group membership caching
- CDR插件开发之GMS插件003 - 编写你的第一个GMS插件
- python中的error:excepted an indented block
- TCP紧急模式理解心得
- 【集训DAY3】挖金矿【二分答案】
- VC++ sourceforge.net中一些好的开源项目
- 谷歌软件工程师是怎样写设计文档的?
- 职称计算机作弊后果,千万别轻忽考试作弊后果,别让它成为你学术生涯中最大的污点!...
- linux 源码安装 飞鸽,Ubuntu中安装编译飞鸽传书
- Kriging插值法
- 带你了解SN74LVC245ADWR