zoukankan      html  css  js  c++  java
  • bzoj1449:[JSOI2009]球队收益/bzoj2895:球队预算

    传送门1449

    传送门2895

    平方很难处理,考虑剩下的比赛所有队全输(只能全输,全赢保证不了费用流的正确性),考虑计算每个队多赢一次的贡献
    拆开:
    (c_i*(x+1)^2+d_i*(y-1)^2-c_i*x^2-d_i*y^2)
    (=2*c_i*x+c_i-2*d_i*y+d_i)
    然后源点向每场比赛连边,容量为1,费用为0,限制每场比赛只能有一场胜利
    每场比赛向参赛的队伍连边,容量为1,费用为1,限制只有一个队伍能赢一场
    每个队伍向汇点连边,容量为1,费用为上面推的,每连一条边将当前队伍的胜负状况修改一下
    然后跑费用流就行了
    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    void read(int &x) {
        char ch; bool ok;
        for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
        for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define rg register
    const int maxn=3e5+10,inf=1e9;queue<int>q;
    int cnt=1,cc[maxn],bb[maxn],v[maxn],w[maxn],ans,num[5010],s,t,a[5010],b[5010],c[5010],d[5010],n,m,pre[maxn*2],nxt[maxn*2],h[maxn];
    int sla[maxn],dis[maxn];bool vis[maxn];
    void add(int x,int y,int z,int d)
    {
        pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z,w[cnt]=d;
        pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=0,w[cnt]=-d;
    }
    bool spfa(int s)
    {
        memset(dis,63,sizeof dis);
        q.push(s),dis[s]=0;
        while(!q.empty())
        {
            int x=q.front();q.pop(),vis[x]=0;
            for(rg int i=h[x];i;i=nxt[i])
                if(v[i]&&dis[pre[i]]>dis[x]+w[i])
                {
                    dis[pre[i]]=dis[x]+w[i],bb[pre[i]]=x,cc[pre[i]]=i;
                    if(!vis[pre[i]])vis[pre[i]]=1,q.push(pre[i]);
                }
        }
        return dis[t]<inf;
    }
    int getans()
    {
        int mn=inf;
        for(rg int i=t;i!=s;i=bb[i])mn=min(v[cc[i]],mn);
        for(rg int i=t;i!=s;i=bb[i])v[cc[i]]-=mn,v[cc[i]^1]+=mn;
        return dis[t]*mn;
    }
    int main()
    {
        read(n),read(m),s=0,t=n+m+1;
        for(rg int i=1;i<=n;i++)read(a[i]),read(b[i]),read(c[i]),read(d[i]);
        for(rg int i=1,x,y;i<=m;i++)
        {
            read(x),read(y);b[x]++,b[y]++,num[x]++,num[y]++;
            add(s,i+n,1,0),add(i+n,x,1,0),add(i+n,y,1,0);
        }
        for(rg int i=1;i<=n;i++)ans=ans+c[i]*a[i]*a[i]+d[i]*b[i]*b[i];
        for(rg int i=1;i<=n;i++)
            while(num[i])add(i,t,1,2*c[i]*a[i]-2*d[i]*b[i]+c[i]+d[i]),a[i]++,b[i]--,num[i]--;
        while(spfa(s))ans+=getans();
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    spring源码学习(一) 小小少年
    mysql索引 小小少年
    Java集合框架个人学习笔记 小小少年
    记录一些自己百度到的问题解决方法
    基于内容的医学图像总结
    黑客与画家 第一章
    问题,不是逃避的
    黑客与画家 第二章
    记录最近一周的感受
    暗时间之体会
  • 原文地址:https://www.cnblogs.com/lcxer/p/10464864.html
Copyright © 2011-2022 走看看