zoukankan      html  css  js  c++  java
  • [BZOJ1449][JSOI2009]球队收益

    bzoj
    luogu

    Description

    在一个篮球联赛里,有(n)支球队,球队的支出是和他们的胜负场次有关系的,具体来说,第i支球队的赛季总支出是(C_i imes x^2+D_i imes y^2,D_i le C_i), 其中(x,y)分别表示这只球队本赛季的胜负场次。现在赛季进行到了一半,每只球队分别取得了(a_i)场胜利和(b_i)场失利。而接下来还有(m)场比赛要进行。问联盟球队的最小总支出是多少。

    sol

    费用流建模。
    先假设剩下的每场比赛双方都输了,这样可以算出一个基础支出。
    因为每场比赛要有一个赢家,所以对于一场比赛,我们需要让参赛双方中的一只球队的胜场++,负场--。
    对于(i)号球队,每有一场比赛由输变为赢,设其当前的胜负场数分别为(x,y),则(Delta)支出=(C_i(x+1)^2+D_i(y-1)^2-C_ix^2-D_iy^2=C_i(2x+1)+D_i(-2y+1))
    可以看出,每有一场比赛由输变为赢,其(Delta)支出的不一样的。
    而且是。。。递增的?
    所以拆边就行了。在跑费用流的时候一定会选择费用更小的边所以答案一定是对的。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 6005;
    struct edge{int to,nxt,w,cost;}a[N<<2];
    int n,m,S,T,A[N],B[N],C[N],D[N],du[N],head[N],cnt=1;
    int dis[N],vis[N],pe[N],ans;queue<int>Q;
    void link(int u,int v,int w,int cost){
    	a[++cnt]=(edge){v,head[u],w,cost};head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0,-cost};head[v]=cnt;
    }
    bool spfa(){
    	memset(dis,63,sizeof(dis));
    	dis[S]=0;Q.push(S);
    	while (!Q.empty()){
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].nxt){
    			int v=a[e].to;
    			if (a[e].w&&dis[v]>dis[u]+a[e].cost){
    				dis[v]=dis[u]+a[e].cost;pe[v]=e;
    				if (!vis[v]) vis[v]=1,Q.push(v);
    			}
    		}
    		vis[u]=0;
    	}
    	if (dis[T]==dis[0]) return false;
    	ans+=dis[T];
    	for (int i=T;i!=S;i=a[pe[i]^1].to)
    		--a[pe[i]].w,++a[pe[i]^1].w;
    	return true;
    }
    int main(){
    	n=gi();m=gi();S=n+m+1;T=S+1;
    	for (int i=1;i<=n;++i)
    		A[i]=gi(),B[i]=gi(),C[i]=gi(),D[i]=gi();
    	for (int i=1;i<=m;++i){
    		int u=gi(),v=gi();
    		link(S,n+i,1,0);link(n+i,u,1,0);link(n+i,v,1,0);
    		++du[u];++du[v];
    	}
    	for (int i=1;i<=n;++i){
    		B[i]+=du[i];ans+=C[i]*A[i]*A[i]+D[i]*B[i]*B[i];
    		for (int j=1;j<=du[i];++j)
    			link(i,T,1,C[i]*(2*A[i]+1)+D[i]*(-2*B[i]+1)),++A[i],--B[i];
    	}
    	while (spfa()) ;
    	printf("%d
    ",ans);return 0;
    }
    
  • 相关阅读:
    live2d 快速实现好看的看板娘特效
    JQuery 日期转换日期方法封装
    SQL Server 之 DateTime的常用方法
    C# 之DateDiff 时间差扩展方法
    SQL Server 之如何查询某数据库下的触发器和语句
    Css 设置固定表格头部,内容可滚动
    jquery 点击tr选中checkbox,解决checkbox的默认点击事件被阻止的问题
    VS切换代码自动补全模式
    C#实现软键盘的几个关键技术介绍
    C# 模拟软件键盘输入,使Winfrom窗体不获取鼠标焦点方法
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9097812.html
Copyright © 2011-2022 走看看