zoukankan      html  css  js  c++  java
  • POJ 2112 Optimal Milking (Dinic + 二分)

    Optimal Milking
    Time Limit: 2000MS   Memory Limit: 30000K
    Total Submissions: 9498   Accepted: 3433
    Case Time Limit: 1000MS

    Description

    FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <= C <= 200) cows. A set of paths of various lengths runs among the cows and the milking machines. The milking machine locations are named by ID numbers 1..K; the cow locations are named by ID numbers K+1..K+C. 

    Each milking point can "process" at most M (1 <= M <= 15) cows each day. 

    Write a program to find an assignment for each cow to some milking machine so that the distance the furthest-walking cow travels is minimized (and, of course, the milking machines are not overutilized). At least one legal assignment is possible for all input data sets. Cows can traverse several paths on the way to their milking machine. 

    Input

    * Line 1: A single line with three space-separated integers: K, C, and M. 

    * Lines 2.. ...: Each of these K+C lines of K+C space-separated integers describes the distances between pairs of various entities. The input forms a symmetric matrix. Line 2 tells the distances from milking machine 1 to each of the other entities; line 3 tells the distances from machine 2 to each of the other entities, and so on. Distances of entities directly connected by a path are positive integers no larger than 200. Entities not directly connected by a path have a distance of 0. The distance from an entity to itself (i.e., all numbers on the diagonal) is also given as 0. To keep the input lines of reasonable length, when K+C > 15, a row is broken into successive lines of 15 numbers and a potentially shorter line to finish up a row. Each new row begins on its own line. 

    Output

    A single line with a single integer that is the minimum possible total distance for the furthest walking cow. 

    Sample Input

    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
    

    Sample Output

    2
    

    Source

     
     
    题意:有K台挤奶机、C头奶牛,以及他们之间距离,每只奶牛都要走到任意一台机器中,每台机器最多为M只奶牛服务,问所有奶牛都完成任务,所走的路程最远的那只奶牛,所走的路程最短可以是多少。

    思路:floyd + 二分+ 最大流。
    很容易想到最大流 建立一个超级源点和汇点把挤奶机和汇点连起来 容量为M ,奶牛与源点连起来 容量为1
    先floyd求出每两个实体间的最小距离 然后二分找出最大
     

    1)先用floyd求到任意milking machine到 任意奶牛之间距离

    2)查找到最长的一条距离,并记录下来为max,那么我们就可以知道,要求的值就是在[0,max]区间

    3)下面就开始二分查找了,找到0到max之间,最小的一个值X,使得这个值刚好能使二分图完成匹配

    4)而使二分图能完成匹配的条件就是,使构造的网络流的最大流的值正好等于奶牛数

     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int VM=300;
    const int INF=0x3f3f3f3f;
    
    int K,C,M;
    int g[VM][VM],map[VM][VM],src,des;
    int dep[VM];
    
    void buildgraph(int x){
        memset(map,0,sizeof(map));
        for(int i=K+1;i<=K+C;i++)   //奶牛与源点相连,流量为1
            map[src][i]=1;
        for(int i=K+1;i<=K+C;i++)   //奶牛与能到达的机器(距离<x的点)相连,流量为1
            for(int j=1;j<=K;j++)
                if(g[i][j]<=x)
                    map[i][j]=1;
        for(int i=1;i<=K;i++)   //机器与汇点相连,流量为 M
            map[i][des]=M;
    }
    
    int BFS(){
        queue<int> q;
        while(!q.empty())
            q.pop();
        memset(dep,-1,sizeof(dep));
        dep[src]=0;
        q.push(src);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int v=src;v<=des;v++)
                if(map[u][v]>0 && dep[v]==-1){
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
        }
        return dep[des]!=-1;
    }
    
    int DFS(int u,int minx){
        if(u==des)
            return minx;
        int tmp;
        for(int v=src;v<=des;v++)
            if(map[u][v]>0 && dep[v]==dep[u]+1 && (tmp=DFS(v,min(minx,map[u][v])))){
                map[u][v]-=tmp;
                map[v][u]+=tmp;
                return tmp;
            }
        dep[u]=-1;
        return 0;
    }
    
    int Dinic(){
        int ans=0,tmp;
        while(BFS()){
            while(1){
                tmp=DFS(src,INF);
                if(tmp==0)
                    break;
                ans+=tmp;
            }
        }
        return ans;
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d%d",&K,&C,&M)){
            src=0, des=K+C+1;
            int i,j,k;
            for(i=1;i<=K+C;i++)
                for(j=1;j<=K+C;j++){
                    scanf("%d",&g[i][j]);
                    if(g[i][j]==0)
                        g[i][j]=INF;
                }
            for(k=1;k<=K+C;k++)
                for(i=1;i<=K+C;i++)
                    for(j=1;j<=K+C;j++)
                        if(g[i][j]>g[i][k]+g[k][j])
                            g[i][j]=g[i][k]+g[k][j];
            int l=0,r=-INF;
            for(i=1;i<=K;i++)
                for(j=K+1;j<=K+C;j++)
                    if(g[i][j]!=INF && r<g[i][j])
                        r=g[i][j];
            //printf("r=%d\n",r);
            int ans=0;
            while(l<=r){
                int mid=(l+r)>>1;
                buildgraph(mid);
                int tmp=Dinic();
                //int tmp=EK();
                if(tmp>=C){
                    ans=mid;
                    r=mid-1;
                }else
                    l=mid+1;
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    sql server 2008收缩数据库日志
    小题大做之MySQL 5.0存储过程编程入门(收藏)
    精进不休 .NET 4.0 (5) C# 4.0 新特性之并行运算(Parallel) (收藏)
    GridView 格式化<收藏>
    MySql捕获sql语句异常的方法
    Windows7发生VS2005无法调试Web项目
    mysql 5.0存储过程学习总结《转载》
    HashMap和Hashtable及HashSet的区别
    iphone 界面实现下拉列表
    Java中堆和栈的区别
  • 原文地址:https://www.cnblogs.com/jackge/p/3053186.html
Copyright © 2011-2022 走看看