zoukankan      html  css  js  c++  java
  • [USACO06FEB]稳定奶牛分配Steady Cow Assignment

    题目链接

    稳定奶牛分配

    题目描述

    农夫约翰有(N(1 le N le 1000))只奶牛,每只奶牛住在(B(1 le B le 20))个奶牛棚中的一个。当然,奶牛棚的容量有限。有些奶牛对它现在住的奶牛棚很满意,有些就不太满意了。
    农夫约翰想要重新安排这些奶牛,使得奶牛的满意度尽可能相同,尽管有可能这意味者所有的奶牛都不喜欢新分配的奶牛棚。
    每只奶牛都按顺序给出她喜欢的奶牛棚。在某个分配方案中,一只奶牛的满意度等于她对她的奶牛棚的评价等级。你的工作是找出一种分配方案使得没有奶牛棚超出它的容量,而且奶牛给分配到的奶牛棚的评价等级的相对范围(即分配到的等级最高的奶牛棚和等级最低的奶牛棚之间的差值)尽可能的小。

    输入格式

    第一行:两个用空格隔开的整数,(N)和B
    第二行到第(N+1)行:每一行都有(B)个用空格隔开的正整数,它们恰好是(1)(B)的一个排列。第(i+1)行的第一个整数是第(i)只奶牛的首选牛棚的编号,该行的第二个整数是第(i)只奶牛的第二选择,等等。
    (N+2)行:(B)个用空格隔开的整数,分别表示这(B)个奶牛棚的容量。这些数的和保证至少为(N)

    输出格式

    一个整数,被分配到的牛棚等级的最小相对差值。

    样例输入

    6 4
    1 2 3 4
    2 3 1 4
    4 2 3 1
    3 1 2 4
    1 3 4 2
    1 4 2 3
    2 1 3 2
    

    样例输出

    2
    

    提示

    每个奶牛都被安排在它的第一选择或第二选择:(1)号牛棚安排(1)号奶牛和(5)号奶牛,(2)号牛棚安排(2)号奶牛,(3)号牛棚安排(4)号奶牛,(4)号牛棚安排(3)号奶牛和(6)号奶牛。

    题解

    要求求出把奶牛分别分配到牛棚后最小的满意度的差值。
    我们看到牛棚的个数很少,只有(20),所以我们可以暴力枚举答案,然后判断能否有安排方法满足条件。
    我们考虑把(s)到每个奶牛连一条流量为(1)的边,然后把所有牛棚到(t)连一条流量为这个牛棚容量的边。
    然后不可能把每个奶牛和牛棚都连边,要求所连所有边中最大的值减最小的值(满意度)要小于等于(ans)
    那么我们只要再根据(ans)枚举区间就好了,然后把满意度在区间内的边全部连上,然后跑一遍网络流。
    如果最大流等于牛的个数(也就是所有牛都能通过在限制范围内的边到牛棚里),那么这个方案就可行。
    当然你可以从小到大枚举(ans),也可以用二分来求(ans)(反正(B)只有20,差距不大)。

    但是你发现如果不加任何优化的话会有一个点跑不过去。
    我们首先用当前弧优化(这个不用说都会加上吧)。
    但还是跑不过去。
    我们考虑(s)到奶牛的流量只有(1),如果找到增广路之后就可以直接退到(s)了,所以我们判断如果当前最大值为(0)的话直接退出,不用再往下扫了。
    但是这还是过不去。
    我们再考虑如果扫完一个点之后,流量还有剩余(就是当前弧优化后到这个点的最大值减去流量之后不为(0)),那么就说明(s)到这个点有流量,但是这个点到(t)已经没有流量了,那么其他点就不能通过这个点到(t)有增广路了,也就是说接下来这个点不用再扫了,那么我们把这个点的(dis[])值设为(-1)就好了。
    加上这些优化就能过所有的点了。
    上代码:

    #include<bits/stdc++.h>
    #define inf 2000000000
    using namespace std;
    int n,b;
    int a[1009][29];
    int s[29];
    struct aa{
        int to,nxt,w;
    }p[50000];
    int h[2009],len;
    void add(int u,int v,int w){
        p[++len].to=v;
        p[len].nxt=h[u];
        p[len].w=w;
        h[u]=len;
        p[++len].to=u;
        p[len].nxt=h[v];
        p[len].w=0;
        h[v]=len;
    }
    int t;
    int uu[5009];
    int l,r;
    int dis[5009];
    bool bfs(){
        memset(dis,-1,sizeof(dis));
        dis[0]=0;
        uu[l=r=1]=0;
        while(l<=r){
            int u=uu[l++];
            for(int j=h[u];j;j=p[j].nxt){
                if(p[j].w && dis[p[j].to]==-1){
                    dis[p[j].to]=dis[u]+1;
                    uu[++r]=p[j].to;
                }
            }
        }
        return dis[t]!=-1;
    }
    int dfs(int u,int mx){
        if(u==t) return mx;
        int oo=0,xx;
        for(int j=h[u];j;j=p[j].nxt){
            if(dis[p[j].to]==dis[u]+1){
                xx=dfs(p[j].to,min(mx,p[j].w));
                oo+=xx;
                mx-=xx;
                p[j].w-=xx;
                p[j^1].w+=xx;
                if(mx==0) break;//最大值为$0$,直接退出
            }
        }
        if(mx!=0) dis[u]=-1;//当前点不用再被扫了
        return oo;
    }
    int dinic(){
        int ans=0;
        while(bfs()) ans+=dfs(0,inf);
        return ans;
    }
    int main(){
        scanf("%d%d",&n,&b);
        t=n+b+1;
        for(int j=1;j<=n;j++)
            for(int i=1;i<=b;i++)
                scanf("%d",&a[j][i]);
        for(int j=1;j<=b;j++)
            scanf("%d",&s[j]);
        for(int l=1;l<=b;l++){
            for(int j=1;j+l-1<=b;j++){
                memset(h,0,sizeof(h));
                len=1;
                for(int i=1;i<=n;i++)
                    add(0,i,1);
                for(int i=1;i<=b;i++)
                    add(n+i,t,s[i]);
                for(int o=1;o<=n;o++)
                    for(int oo=j;oo<=j+l-1;oo++)
                        add(o,n+a[o][oo],1);
                if(dinic()==n){
                    printf("%d",l);
                    return 0;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【Python】关于Python多线程的一篇文章转载
    【编码备份】1.9从Excel中导入用户名进行测试,用户一次进入系统进行答题测试。
    【实战】10.10.1.9考试系统代码完成一次答题代码备份
    Python几种并发实现方案的性能比较
    LoadRunner中获取当前系统时间方法
    [Jmeter]jmeter之脚本录制与回放,优化(windows下的jmeter)
    多少秒后跳转到指定页面
    浮动的三个特点很重要。
    HTML表格中<td scope="col">与<td scope="row">的含义
    简单编程思想
  • 原文地址:https://www.cnblogs.com/linjiale/p/12026105.html
Copyright © 2011-2022 走看看