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是合法的,反之亦然。

  • 相关阅读:
    函数指针与函数声明
    long和int的区别
    pthread_create传递参数
    C语言中的static 详细分析
    linux 读写锁应用实例
    linux使用读写锁pthread_rwlock_t
    linux的<pthread.h>
    时间:UTC时间、GMT时间、本地时间、Unix时间戳
    等号赋值与memcpy的效率问题
    单链表带头结点&不带头结点
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5506033.html
Copyright © 2011-2022 走看看