• 题解 最优的挤奶方案(Optimal Milking)


    最优的挤奶方案(Optimal Milking)

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

    题目描述

    农场主 John 将他的 K(1≤K≤30)个挤奶器运到牧场,在那里有 C(1≤C≤200)头奶牛,在奶
    牛和挤奶器之间有一组不同长度的路。K个挤奶器的位置用1~K的编号标明,奶牛的位置用K+1~
    K+C 的编号标明。
    每台挤奶器每天最多能为 M(1≤M≤15)头奶牛挤奶。
    编写程序,寻找一个方案,安排每头奶牛到某个挤奶器挤奶,并使得 C 头奶牛需要走的所有
    路程中的最大路程最小。每个测试数据中至少有一个安排方案。每条奶牛到挤奶器有多条路。

    输入

    第 1 行为 3 个整数 K、C 和 M。
    第 2~K+C+1 行,每行有 K+C 个整数,描述了奶牛和挤奶器(二者合称实体)之间的位置,
    这 K+C 行构成了一个沿对角线对称的矩阵。第 2 行描述了第 1 个挤奶器离其他实体的距离,…,
    第 K+1 行描述了第 K 个挤奶器离其他实体的距离;第 K+2 行描述了第 1 头奶牛离其他实体的距
    离,…。这些距离为不超过 200 的正数。实体之间如果没有直接路径相连,则距离为 0。实体与
    本身的距离(即对角线上的整数)也为 0。

    输出

    输出一个整数,为所有方案中,C 头奶牛需要走的最大距离的最小值。
     

    样例输入

    2 3 2
    0 3 2 1 1
    3 0 3 2 0
    2 3 0 1 0
    1 2 1 0 2
    1 0 0 2 0

    样例输出

    2
    题解:
    又是一道网络流套二分的题目。
    1.先用floyd求一个最短路map。
    2.每一次虚拟一个源点和挤奶器建边,虚拟一个汇点和奶牛建边。
    3.Dinic跑起来!!!
    4.然后。。。就没有然后了。。。
    AC代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    using namespace std;
    int n,m,l,s;
    int map[301][301],cap[301][301],depth[301];
    int read()
    {
        int ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    bool bfs()
    {
        memset(depth,0,sizeof(depth));
        int b[30001],head=0,tail=0,i;
        b[tail++]=0;
        depth[0]=1;
        while(head!=tail)
        {
            int x=b[head++];
            for(i=0; i<=s+1; i++)
            {
                if(depth[i]==0&&cap[x][i]>0)
                {
                    depth[i]=depth[x]+1;
                    b[tail++]=i;
                }
            }
        }
        if(depth[s+1]!=0)return 1;
        else return 0;
    }
    int dfs(int root,int flow)
    {
        if(root==s+1)return flow;
        int res=0;
        for(int i=0; i<=s+1; i++)
        {
            if(cap[root][i]>0&&depth[i]==depth[root]+1)
            {
                int tmp=dfs(i,min(flow-res,cap[root][i]));
                cap[root][i]-=tmp;
                cap[i][root]+=tmp;
                res+=tmp;
                if(res==flow)return flow;
            }
        }
        return res;
    }
    bool judge(int mid)
    {
        memset(cap,0,sizeof(cap));
        int i,j,k;
        for(i=1; i<=n; i++)
            cap[0][i]=l;
        for(i=1; i<=n; i++)
            for(j=n+1; j<=s; j++)
                if(map[i][j]<=mid)
                    cap[i][j]=1;
        for(i=n+1; i<=s; i++)
            cap[i][s+1]=1;
        int root=0,f=0;
        while(bfs())
        {
            f+=dfs(root,2000000000);
        }
        return f>=m;
    }
    int main()
    {
        int i,j,k;
        n=read();
        m=read();
        l=read();
        s=n+m;
        for(i=1; i<=s; i++)
            for(j=1; j<=s; j++)
            {
                map[i][j]=read();
                if(map[i][j]==0)map[i][j]=2e8;
            }
        for(k=1; k<=s; k++)
            for(i=1; i<=s; i++)
                for(j=1; j<=s; j++)
                    if(i!=j&&j!=k&&k!=i&&map[i][k]+map[k][j]<map[i][j])
                        map[i][j]=map[i][k]+map[k][j];
        int l=0,r=5000000,ans=5000000;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(judge(mid))
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }

    总结:

    1.最大值不能赋太大,否则会溢出。

    2.最好还是用非递归的Dinic。

  • 相关阅读:
    c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)
    linux服务之rsyslog
    java实现第五届蓝桥杯李白打酒
    java实现第五届蓝桥杯李白打酒
    java实现第五届蓝桥杯猜字母
    java实现第五届蓝桥杯猜字母
    java实现第五届蓝桥杯大衍数列
    java实现第五届蓝桥杯大衍数列
    redis 安装启动及设置密码<windows>
    redis密码设置、访问权限控制等安全设置
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/6830413.html
Copyright © 2020-2023  润新知