• 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]*x^2+D[i]*y^2,现在是C[i]*(x+1)^2+D[i]*(y-1)^2
    那么在这支球队赢x场输y场的时候把一场输的变成赢的,对答案的贡献就是两个相减
    对于一支一开始赢x场输y场的球队,我们向T连边,代价是从(x,y)变成(x+1,y-1)的代价。
    然后还有从(x+1,y-1)到(x+2,y-2)……
    因为是最小费用最大流,正确性显然
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<ctime>
    #define LL long long
    #define inf 0x3ffffff
    #define S 0
    #define T n+m+1
    #define N 6010
    using namespace std;
    inline LL read()
    {
        LL 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;
    }
    struct edge{int to,next,from,v,c;}e[10*N];
    struct match{int x,y;}M[100010];
    int head[N],from[N],dist[N],q[N];
    bool mrk[N];
    int n,m,ans,cnt=1;
    int a[N],b[N],C[N],D[N];
    inline void ins(int u,int v,int w,int c)
    {
    	e[++cnt].to=v;
    	e[cnt].v=w;
    	e[cnt].c=c;
    	e[cnt].from=u;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void insert(int u,int v,int w,int c)
    {
    	ins(u,v,w,c);
    	ins(v,u,0,-c);
    }
    inline bool spfa()
    {
    	for(int i=0;i<=T;i++)dist[i]=inf;
    	int t=0,w=1;
    	dist[S]=0;q[0]=S;mrk[S]=1;
    	while (t!=w)
    	{
    		int now=q[t++];if (t==6005)t=0;
    		for (int i=head[now];i;i=e[i].next)
    			if(e[i].v&&dist[now]+e[i].c<dist[e[i].to])
    			{
    				dist[e[i].to]=dist[now]+e[i].c;
    				from[e[i].to]=i;
    				if (!mrk[e[i].to])
    				{
    					mrk[e[i].to]=1;
    					q[w++]=e[i].to;
    					if(w==6005)w=0;
    				}
    			}
    		mrk[now]=0;
    	}
    	return dist[T]!=inf;
    }
    inline void mcf()
    {
    	int x=inf;
    	for (int i=from[T];i;i=from[e[i].from])
    		x=min(x,e[i].v);
    	for (int i=from[T];i;i=from[e[i].from])
    	{
    		e[i].v-=x;
    		e[i^1].v+=x;
    		ans+=x*e[i].c;
    	}
    }
    int main()
    {
    	n=read();m=read();
    	for (int i=1;i<=n;i++)
    	{
    		a[i]=read();
    		b[i]=read();
    		C[i]=read();
    		D[i]=read();
    	}
    	for(int i=1;i<=m;i++)
    	{
    		M[i].x=read();
    		M[i].y=read();
    		b[M[i].x]++;
    		b[M[i].y]++;
    		insert(S,i,1,0);
    		insert(i,m+M[i].x,1,0);
    		insert(i,m+M[i].y,1,0);
    	}
    	for (int i=1;i<=n;i++)
    		ans+=a[i]*a[i]*C[i]+b[i]*b[i]*D[i];
    	for (int i=1;i<=m;i++)
    	{
    		int x=M[i].x,y=M[i].y;
    		insert(m+x,T,1,2*a[x]*C[x]-2*b[x]*D[x]+C[x]+D[x]);
    		a[x]++;b[x]--;
    		insert(m+y,T,1,2*a[y]*C[y]-2*b[y]*D[y]+C[y]+D[y]);
    		a[y]++;b[y]--;
    	}
    	while (spfa())mcf();
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

    S向所有比赛连边,所有比赛向两队连边。所有队伍
    ——by zhber,转载请注明来源
  • 相关阅读:
    老鸟的Python新手教程
    vs2010经常使用快捷键
    SQL基础--&gt; 约束(CONSTRAINT)
    哈哈,做题了
    【网络协议】TCP中的四大定时器
    JAVA反射机制
    JUnit入门
    怎样将程序猿写出来的程序打包成安装包(最简单的)
    事件传递机制总结
    理解class.forName()
  • 原文地址:https://www.cnblogs.com/zhber/p/4215838.html
Copyright © 2020-2023  润新知