zoukankan      html  css  js  c++  java
  • [POJ3189][cqbzoj1640]稳定的奶牛分配 解题报告

    [POJ3189]稳定的奶牛分配

    时间限制: 1 Sec 内存限制: 64 MB

    题目描述

    农夫约翰有N(1<=N<=1000)只奶牛,每只奶牛住在B(1<=B<=20)个奶牛棚中的一个。当然,奶牛棚的容量有限。有些奶牛对它现在住的奶牛棚很满意,有些就不太满意了。

    农夫约翰想要重新安排这些奶牛,使得奶牛的满意度尽可能相同,尽管有可能这意味者所有的奶牛都不喜欢新分配的奶牛棚。

    每只奶牛都按顺序给出她喜欢的奶牛棚。在某个分配方案中,一只奶牛的满意度等于她对她的奶牛棚的评价等级。你的工作是找出一种分配方案使得没有奶牛棚超出它的容量,而且奶牛给分配到的奶牛棚的评价等级的范围(即分配到的等级最高的奶牛棚和等级最低的奶牛棚之间的差值+1)尽可能的小。

    附上原文:the size of the range (i.e., one more than the positive difference between the the highest-ranked barn chosen and that lowest-ranked barn chosen) of barn rankings the cows give their assigned barns is as small as possible.

    输入

    第1行:两个用空格隔开的整数,N和B
    第2..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.枚举答案上界u与下界d(就是奶牛的满意度上界和下界)
    2.按照u和d建图
    建图方法:
    - 1.每个奶牛和每个牛棚代表一个节点
    - 2.源点向每头奶牛连边,边权为1 代表这头奶牛只能使用一次
    - 3.每头奶牛向这头奶牛选择中满意度在[u,d]之间的牛棚连一条权值为1的边
    4.每个牛棚向汇点连一条权值为牛棚容量的边
    3.跑最大流
    4.判断flow是否等于奶牛数量 如果相等,ans=min(ans,d-u+1);

    如果把枚举换成二分答案建图跑得飞快
    但是原谅我太懒提供不了二分版本答案(. V . )

    接下来是代码

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    namespace isap{
    const int MAXN=2000;
    const int MAXM=1000000;
    const int INF=0x7f7f7f7f;
    const int INF4BIT=0x7f;
    struct Node{
        int v,c,nxt,bk;
    }nodes[MAXM];
    int head[MAXN],e_total;
    int n,S,T;
    inline void addedge(int a,int b,int c){
        e_total++;
        nodes[e_total].v=b;
        nodes[e_total].c=c;
        nodes[e_total].nxt=head[a];
        nodes[e_total].bk=e_total+1;
        head[a]=e_total;
        e_total++;
        nodes[e_total].v=a;
        nodes[e_total].c=0;
        nodes[e_total].nxt=head[b];
        nodes[e_total].bk=e_total-1;
        head[b]=e_total;
    }
    bool vis[MAXN];
    int d[MAXN],vd[MAXN];
    void spfa(int start){
        queue<int>que;
        que.push(start);
        vis[start]=true;
        while(!que.empty()){
            int u=que.front();
            que.pop();
            vis[u]=false;
            for(int e=head[u];e;e=nodes[e].nxt)
                if(d[nodes[e].v]>d[u]+1){
                    d[nodes[e].v]=d[u]+1;
                    if(!vis[nodes[e].v]){
                        vis[nodes[e].v]=true;
                        que.push(nodes[e].v);
                    }
                }
        }
        for(int i=1;i<=n;i++)
            if(d[i]<=n)vd[d[i]]++;
    }
    int aug(int u,int augv){
        if(u==T)return augv;
        int last=augv;
        for(int e=head[u];e;e=nodes[e].nxt)
            if(nodes[e].c&&d[nodes[e].v]+1==d[u]){
                int t=aug(nodes[e].v,min(nodes[e].c,last));
                nodes[e].c-=t;
                nodes[nodes[e].bk].c+=t;
                last-=t;
                if(d[S]>=n||!last)return augv-last;
            }
        if(augv==last){
            vd[d[u]]--;
            if(!vd[d[u]]){d[S]=n+1;return 0;}
            d[u]=n+1;
            for(int e=head[u];e;e=nodes[e].nxt)
                if(nodes[e].c)d[u]=min(d[u],d[nodes[e].v]+1);
            vd[d[u]]++;
        }
        return augv-last;
    }
    int sap(){
        for(int i=1;i<=n;i++)
            d[i]=INF;
        d[T]=0;
        spfa(T);
        int flow=0;
        while(d[S]<n)flow+=aug(S,INF);
        return flow;
    }
    void clear(){
        memset(nodes,0,sizeof nodes);
        memset(vis,0,sizeof vis);
        memset(head,0,sizeof head);
        e_total=0;
        memset(vd,0,sizeof vd);
    }
    }
    int n,m;
    int inp[1200][30];
    int bns[30];
    void build(int l,int r){
        isap::S=1;
        isap::T=isap::S+n+m+1;
        isap::n=isap::T;
        for(int i=1;i<=n;i++){
            isap::addedge(isap::S,isap::S+i,1);
            for(int j=l;j<=r;j++)
                isap::addedge(isap::S+i,isap::S+n+inp[i][j],1);
        }
        for(int i=1;i<=m;i++)
            isap::addedge(isap::S+n+i,isap::T,bns[i]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&inp[i][j]);
        for(int i=1;i<=m;i++)
            scanf("%d",&bns[i]);
        int ans=m;
        for(int i=1;i<=m;i++)
            for(int j=i;j<=m;j++){
                if(j-i+1>=ans)continue;
                isap::clear();
                build(i,j);
                int t=isap::sap();
                if(t>=n)ans=min(j-i+1,ans);
            }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    java Activiti 工作流引擎 SSM 框架模块设计方案
    自定义表单 Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    数据库设计的十个最佳实践
    activiti 汉化 stencilset.json 文件内容
    JAVA oa 办公系统模块 设计方案
    java 考试系统 在线学习 视频直播 人脸识别 springboot框架 前后分离 PC和手机端
    集成 nacos注册中心配置使用
    “感恩节 ”怼记
    仓颉编程语言的一点期望
    关于System.out.println()与System.out.print("\n")的区别
  • 原文地址:https://www.cnblogs.com/Hineven/p/5843567.html
Copyright © 2011-2022 走看看