zoukankan      html  css  js  c++  java
  • TTTTTTTTTTTT POJ 2112 奶牛与机器 多重二分匹配 跑最大流 建图很经典!!

    Optimal Milking
    Time Limit: 2000MS   Memory Limit: 30000K
    Total Submissions: 15682   Accepted: 5597
    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

    2112题意:给出K+C个点,前K个点代表牛棚,之后的C个点代表牛,所有的牛都要转移到牛棚中去,然而每个牛棚最多能容纳M头牛,问最短多长时间可以将所有牛转移到牛棚中去(每条边不限制同一时间通过数量,牛可以同时移动)。输入数据第一行三个整数K C M,接下来一个邻接矩阵D,D[i][j]表示点i到点j的距离,D[i][i] = 0,当i!=j时D[i][j] == 0表示i与j之间没有直接的路径。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    #define MM(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    typedef unsigned long long ULL;
    const int mod = 1000000007;
    const double eps = 1e-10;
    const int inf = 0x3f3f3f3f;
    const int big=50000;
    int max(int a,int b) {return a>b?a:b;};
    int min(int a,int b) {return a<b?a:b;};
    struct edge{
       int to,cap,rev;
    };
    vector<edge> G[250];
    int tol,k,c,m,level[250],iter[250],mp[250][250];
    
    void add_edge(int u,int v,int cap)
    {
        G[u].push_back(edge{v,cap,G[v].size()});
        G[v].push_back(edge{u,0,G[u].size()-1});
    }
    
    void bfs(int s)
    {
        queue<int> q;
        q.push(s);
        level[s]=1;
        while(q.size())
        {
            int now=q.front();q.pop();
            for(int i=0;i<G[now].size();i++)
            if(G[now][i].cap>0)
            {
                edge e=G[now][i];
                if(level[e.to]<0)
                  {
                      level[e.to]=level[now]+1;
                      q.push(e.to);
                  }
            }
        }
    }
    int dfs(int s,int t,int minn)
    {
        if(s==t)
            return minn;
        for(int &i=iter[s];i<G[s].size();i++)
        {
            edge &e=G[s][i];
            if(level[e.to]>level[s]&&e.cap>0)
            {
                int k=dfs(e.to,t,min(minn,e.cap));
                if(k>0)
                 {
                     e.cap-=k;
                     G[e.to][e.rev].cap+=k;
                     return k;
                 }
            }
        }
        return 0;
    }
    
    int  max_flow(int s,int t)
    {
        int ans=0,temp;
        for(;;)
        {
            memset(level,-1,sizeof(level));
            bfs(s);
            if(level[t]<0)
                return ans;
            memset(iter,0,sizeof(iter));
            while((temp=dfs(s,t,inf))>0)
                ans+=temp;
        }
        return ans;
    }
    
    void buildgraph(int mid)
    {
        for(int i=0;i<=tol+1;i++) G[i].clear();
    
        for(int i=1;i<=k;i++)
            add_edge(0,i,m);
    
        for(int i=1;i<=k;i++)
           for(int j=k+1;j<=k+c;j++)
               if(mp[i][j]<=mid)
                   add_edge(i,j,1);
    
        for(int j=k+1;j<=k+c;j++)
            add_edge(j,tol+1,1);
    }
    
    void floyd()
    {
        for(int k=1;k<=tol;k++)
            for(int i=1;i<=tol;i++)
                for(int j=1;j<=tol;j++)
                    mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
    
    }
    
    int main()
    {
       while(~scanf("%d %d %d",&k,&c,&m))
        {
            tol=k+c;
            MM(mp,inf);
            for(int i=1;i<=tol;i++)
                for(int j=1;j<=tol;j++)
               {
                 int w;
                 scanf("%d",&w);
                 if(!w&&(i!=j)) w=inf;
                 mp[i][j]=w;
               }
    
            floyd();
    
            int l=-1,r=200*55;
            while(r-l>1)
            {
               int mid=(l+r)>>1;
               buildgraph(mid);
               if(max_flow(0,tol+1)>=c) r=mid;
               else l=mid;
            }
            printf("%d
    ",r);
        }
        return 0;
    }
    

      分析:很经典的一道题,

    1.因为要最小化最大长度,所以想到了二分;

    2.利用Floyd求出任意两点之间的距离

    2.二分出一个mid值后,重新建图,对于奶牛与机器之间距离<=mid的建立一条容量为1的边,否则不建边,最后看最大流跑出来的数值是否是==牛的个数的,如果是,则说明该mid是合法的,反之亦然。

  • 相关阅读:
    [前端插件]Bootstrap Table服务器分页与在线编辑应用总结
    Accord.NET_Naive Bayes Classifier
    Accord.NET入门
    [C++]STL容器Vector的内存释放
    [设计模式]适配器模式与外观模式
    [设计模式]工厂模式
    Linux下spi驱动开发
    Qt移植对USB鼠标键盘、触摸屏的支持
    linux设备模型详解 http://blog.csdn.net/linux_xiaomugua/article/details/6989386
    LGPL协议的理解
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5506033.html
Copyright © 2011-2022 走看看