zoukankan      html  css  js  c++  java
  • YYH的球盒游戏(NOIP模拟赛Round 6)

    题目描述

    YYH有一些总共有种颜色的球,他有颜色的球个。他同样有个盒子,第个盒子能放个球。

    他的目标是把这个球按规则放进个盒子里:

    • 对于一个盒子,对于每种颜色的球至多只能放个。

    • 把颜色为的球放进盒子,他能获得的收益。

    • 由于盒子有一定的额外承受能力,所以在最后,对于一个盒子,如果里面的球的数量比多了,那么YYH会有的花费。

    YYH不需要把每个球都放到盒子里,他只希望他的收益与花费之差最大。

    输入输出格式

    第一行输入两个整数,,为球颜色个数和盒子个数。

    第二行输入个整数,,分别表示每种颜色小球的个数

    第三行输入个整数,,分别表示每个盒子的基础承载能力。

    接下来的行每行个数,第行第个数为,表示将颜色为的球放进盒子的收益。 

    输出一个整数为YYH最大的收益与花费之差

    这题的算法优化真是博大精深、

    具体我们一个一个来讲。

    我们先看这道题的算法,(这。。裸的费用流啊。。。)

    然后我们发现负边(好吧,其实没有什么用。spfa可以跑)

    首先所有的球都要向源点连费用0,流量为球的数量的边

    然后我们考虑每一个球都要到汇点,所以从盒子向汇点连费用0,流量inf的边。

    对于每一个球向每一个盒子连费用为-c(c为收益),流量为1的边。

    重点来了:怎么处理多放?

    我们已知一个公式 n^2-(n-1)^2=n*2-1;

    所以我们从每一个盒子向汇点连流量为1,费用为2*n-1的边(一共要连n-x(x为盒子的容量)次)

    最后输出-spfa_flow即可

    神奇的优化:

    TOP1:当前弧优化(扔了!明明跑的更慢)

    TOP2:spfa优化(SLF)如果当前点的距离比队首的距离还小就将它插入队首

    TOP3:快读(。。。。醉了。。)

    其实还有TOP0:费用流中spfa倒着做跑的更快??(学长说的玄学优化)

    然后就跑的飞快啦!

    再打一个多路增广简直快的飞起

    下面贴代码

    #include<cstdio> 
    #include<cstring> 
    #define inf 0x3f3f3f3f 
    #define r register  
    #define min(a,b) (a)<(b)?(a):(b)  
    #ifndef Debug 
        #define getchar() (SS==TT&&(TT=(SS=BB)+fread(BB,1,1<<15,stdin),TT==SS)?EOF:*SS++) 
        char BB[1<<15],*SS=BB,*TT=BB; 
    #endif 
    inline int read(){  
        r int x; r bool f; r char c;  
        for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');  
        for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');  
        return f?-x:x;  
    }  
    using namespace std; 
    struct edge{ 
        int to,next,c,w; 
    }g[50005]; 
    int d[501],que[5001],head[501]; 
    bool visit[501]; 
    int S,T,num=1; 
    void ins(int u,int v,int c,int w){g[++num].next=head[u];head[u]=num;g[num].c=c;g[num].w=w;g[num].to=v;} 
    void insw(int u,int v,int c,int w){ins(u,v,c,w);ins(v,u,-c,0);} 
    bool spfa(int S,int T) 
    { 
        memset(visit,0,sizeof(visit));  
        memset(d,inf,sizeof(d)); 
        int h=1,t=1; 
        que[h]=T; 
        d[T]=0; 
        visit[T]=true; 
        while(h<=t) 
        { 
            int tmp=que[h++]; 
            for(r int i=head[tmp];i;i=g[i].next) 
            { 
                if(g[i^1].w&&d[tmp]-g[i].c<d[g[i].to]) 
                { 
                    d[g[i].to]=d[tmp]-g[i].c;//d[g[i].to]=d[tmp]+g[i^1].c; 
                    if (!visit[g[i].to]) 
                    { 
                        visit[g[i].to]=true; 
                        if (d[g[i].to]<d[que[h]]) que[--h]=g[i].to;//youhua 
                        else que[++t]=g[i].to; 
                    } 
                } 
            }visit[tmp]=0; 
        } 
        return d[S]!=inf; 
    } 
    int dfs(int S,int T,int flow,int &ans) 
    { 
        visit[S]=true; 
        if(S==T)return flow; 
        int used=0,w; 
        for(r int i=head[S];i;i=g[i].next) 
        { 
            if(!visit[g[i].to]&&g[i].w&&d[S]-d[g[i].to]==g[i].c) 
            { 
                if(w=dfs(g[i].to,T,min(g[i].w,flow-used),ans)) 
                { 
                    used+=w; 
                    g[i].w-=w; 
                    g[i^1].w+=w; 
                    ans+=g[i].c*w; 
                    if(used==flow)return flow; 
                } 
            } 
        } 
        return used; 
    } 
    int mcf(int S,int T){ 
        r int ans=0; 
        while(spfa(S,T)) 
            do
            memset(visit,0,sizeof(visit)); 
            while(dfs(S,T,inf,ans)); 
        return ans; 
    } 
    int main(){ 
        r int n=read(),m=read(); 
        S=0;T=n+m+5; 
        r int x; 
        for(int i=1;i<=n;i++) 
        { 
            x=read(); 
            insw(S,i,0,x); 
            insw(i,T,0,x); 
        } 
        for(r int i=1;i<=m;i++) 
        { 
            x=read(); 
            insw(i+n,T,0,x); 
            for(r int j=0;j<=n-x;j++)insw(i+n,T,(j<<1)|1,1); 
        } 
        for(r int i=1;i<=n;i++) 
            for(r int j=1;j<=m;j++) 
            { 
                x=read(); 
                insw(i,n+j,-x,1);    
            } 
        printf("%d
    ",-mcf(S,T)); 
        return 0;    
    } 
  • 相关阅读:
    如何使用dig命令挖掘域名解析信息
    网络地址转换 NAT 配置
    Win10 安装子系统 GUI 界面
    送给发烧友:Python条件语句的七种写法T
    这是一个可以显示Linux命令的工具
    网页游戏破解 我是武神
    仙侠道破解
    心动最新页游 仙侠道 破解笔记
    通用网页游戏伤害公式。
    mysql: error while loading shared libraries: libmysqlclient.so.16
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6930202.html
Copyright © 2011-2022 走看看