• 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

    HINT

    这题挺逗的。。。很好看出来是网络流
    难点就在于你不能在跑网络流的时候把输赢的利益一起算上
    所以做法很光(you)棍(xiu):每场比赛每队都算输,然后看看是哪个赢
    根据它给的公式可以拆开,对于每一个球队,就建出每多赢一场的利益
    它说明了它Ci>=Di,所以这肯定是递增的,就可以直接跑最小费用最大流了
    代码如下:
    //MT_LI
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<map>
    #include<bitset>
    #include<set>
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    #define pll pair<long long,long long>
    #define pii pair<int,int>
    using namespace std;
    inline int read()
    {
        int f=1,x=0;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;
    }
    int stack[20];
    inline void write(int x)
    {
        if(x<0){putchar('-');x=-x;}
        if(!x){putchar('0');return;}
        int top=0;
        while(x)stack[++top]=x%10,x/=10;
        while(top)putchar(stack[top--]+'0');
    }
    inline void pr1(int x){write(x);putchar(' ');}
    inline void pr2(int x){write(x);putchar('
    ');}
    struct node{
        int x,y,c,d,next,other;
    }a[21000];int len,last[11000];
    void ins(int x,int y,int c,int d)
    {
        a[++len]=(node){x,y,c,d,last[x],len+1};last[x]=len;
        a[++len]=(node){y,x,0,-d,last[y],len-1};last[y]=len;
    }
    int lose[5100],win[5100],c[5100],d[5100];
    int n,m,st,ed;
    int head,tail,list[110000];
    int D[11000],ans;
    int cc[11000],pre[11000];
    bool v[11000];
    bool spfa()
    {
        for(int i=1;i<=ed;i++)D[i]=9999999;
        D[st]=0;
        memset(v,false,sizeof(v));v[st]=true;
        memset(cc,0,sizeof(cc));cc[st]=99999999;
        list[1]=st;head=1;tail=2;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(a[k].c>0&&D[y]>D[x]+a[k].d)
                {
                    D[y]=D[x]+a[k].d;
                    pre[y]=k;
                    cc[y]=min(cc[x],a[k].c);
                    if(v[y]==false)
                    {
                        v[y]=true;
                        list[tail++]=y;
                    }
                }
            }
            head++;
            v[x]=false;
        }
        if(D[ed]==9999999)return false;
        ans+=D[ed]*cc[ed];
        int x=ed;
        while(x!=0)
        {
            int k=pre[x];
            a[k].c-=cc[ed];a[a[k].other].c+=cc[ed];
            x=a[k].x;
        }
        return true;
    }
    int match[5100];
    int main()
    {
        n=read();m=read();
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)win[i]=read(),lose[i]=read(),c[i]=read(),d[i]=read();
        st=0;ed=n+m+1;
        for(int i=1;i<=m;i++)
        {
            ins(st,i,1,0);
            int x=read(),y=read();
            ins(i,x+m,1,0);ins(i,y+m,1,0);
            match[x]++,match[y]++;
        }
        for(int i=1;i<=n;i++)lose[i]+=match[i];
        int sum=0;
        for(int i=1;i<=n;i++)
            sum+=win[i]*win[i]*c[i]+lose[i]*lose[i]*d[i];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=match[i];j++)
            {
                ins(i+m,ed,1,2*c[i]*win[i]+c[i]+d[i]-2*d[i]*lose[i]);
                win[i]++,lose[i]--;
            }
        ans=0;
        while(spfa());
        printf("%d
    ",sum+ans);
        return 0;
    }
  • 相关阅读:
    转自:java 文件格式二进制头文件校验
    转载:Web安全X-FRAME-OPTIONS 出现两个或多个的原因
    转载:Web安全 之 X-Frame-Options响应头配置
    JavaWeb-用过滤器修改请求的返回状态码
    文件上传漏洞(绕过姿势)
    一个神奇的bug
    在mac上访问自带服务器权限问题
    学习使用crosswalk
    多个target下编译的时候出错问题的解决
    解决mac插入U盘不显示标识问题
  • 原文地址:https://www.cnblogs.com/MT-LI/p/10376449.html
Copyright © 2020-2023  润新知