poj 2112 Optimal Milking (+ half maximum flow or multiple bipartite graph matching)

Topic links: http://poj.org/problem?id=2112

 

The meaning of problems: there are n milking machines, m cows, milking machines each handle up to k cows. Gives the milking machine, the distance between the cows, milking asked after the completion of the task, the most long-distance walking cows minimized and output.

 

Idea: to minimize the maximum distance, it is easy to know when the binary process. But the dichotomy determine what conditions is it?

Case half of the distance is to set up so cows can go to the milking machine. Such a problem becomes a bipartite graph matching, n milking machine is left, the right is m cows, each cow must match a milking machine. And because the number of hits with a milking machine, is a bipartite graph multiple matches. As long as the maximum number of matches is the number m of the cow's head from the two points it is established. (Multiple bipartite graph matching)

 

Of course, network flow with the maximum flow is to be completed, generally bipartite graph may flow with the network. Figure that how to build it?

As long build two virtual point, a start point, an end point, the start point is connected to each milking machine, the flow rate is k, each cow connection end points, the flow rate is 1, it is determined whether the cow milking machine may be connected according to the half of the distance, it can be traffic is 1. As long as the maximum flow is m, then the half of the distance is possible.

Of course, there can be a distance between the dots is calculated by floyed.

 

Multiple Match code bipartite graph:

#include <the iostream> 
#include <algorithm> 
#include <cstdio> 
#include <CString> 
#include <Queue>
 #define INF 0x3f3f3f3f
 the using  namespace STD; 
typedef Long  Long LL;
 const  int MAXN = 350 ;
 int MP [MAXN] [ MAXN];
 BOOL Used [MAXN];
 int CNT [MAXN]; // CNT [i] of the i-th recording is now the number of cows teat 
int MAT [MAXN] [MAXN], n-, m, K; // MAT [i] [j] denotes the i-th unit of the j-th matching milking cows who 
int G [MAXN] [MAXN]; 

BOOL DFS ( intx) // match 
{
     for ( int i = . 1 ; i <= n-; i ++ ) 
    { 
        IF ! (MP [x] [i] && Used [i]) // denotes the x-th cows matching pressing the i-th milk machine 
        { 
            Used [I] = . 1 ;
             IF (CNT [I] <K) // and does not limit the number of the milking machine, direct match 
            { 
                MAT [I] [CNT [I] ++] = X;
                 return  to true ; 
            } 
            the else // maximum number, look on the cow milking machine so if you can make location 
            {
                 for ( int J =0 ; J <K; J ++ ) 
                { 
                    IF (DFS (MAT [I] [J])) // allows the position 
                    { 
                        MAT [I] [J] = X;
                         return  to true ; 
                    } 
                } 
            } 
        } 
    } 
    return  to false ; 
} 

BOOL Solve () 
{ 
    for ( int I = n-+ . 1 ; I <= n-m +; I ++) // see if it matches the cows 
    {
         for ( int J = . 1; J <= n-; J ++ ) 
            Used [J] = 0 ;
         IF (! DFS (I)) // I do not match cows 
            return  to false ; 
    } 
    return  to true ; 
} 

BOOL Check ( int X) // determination condition, a distance x is established 
{ 
    Memset (CNT, 0 , the sizeof (CNT)); 
    Memset (MP, 0 , the sizeof (MP));
     for ( int I = . 1 ; I <= n-; I ++ )
         for ( int J = n-+ . 1;j<=m+n;j++)
            if(g[i][j]<=x)
                mp[i][j]=mp[j][i]=1;
    if(solve())
        return true;
    return false;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n+m;i++)
    {
        for(int j=1;j<=n+m;j++)
        {
            scanf("%d",&g[i][j]);
            if(i!=j&&!g[i][j])
                g[i][j]=inf;
        }
    }
    for(int k=1;k<=n+m;k++)//floyed求最短距离 
        for(int i=1;i<=n+m;i++)
            for(int j=1;j<=n+m;j++)
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);    
                        
    int l=0,r=inf,mid;
    while(r>=l)//Dichotomous outcomes 
    { 
        MID = (R & lt + L) / 2 ;
         IF (Check (MID)) 
            R & lt = mid- . 1 ;    
         the else 
            L = MID + . 1 ; 
    } 
    the printf ( " % D \ n- " , L);
     return  0 ; 
}
View Code

 

Network flow Code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=350;
int g[maxn][maxn];
struct node{
    int u,v,w,nxt;
}e[maxn*maxn];
int h[maxn],depth[maxn],n,m,k,st,ed;
int cnt;

void add(int u,int v,int W) // build FIG remember reverse sides built 
{ 
    E [CNT] .v = V; E [CNT] .W = W; 
    E [CNT] .nxt = H [U]; H [U] = CNT ++ ; 
    
    E [CNT] .v = U, E [CNT] .W = 0 ; 
    E [CNT] .nxt = H [V]; H [V] = CNT ++ ; 
} 

BOOL BFS () { // dinic-- minutes FIG layer 
    Queue < int > que; 
    Memset (depth, 0 , the sizeof (depth)); 
    que.push (ST); 
    depth [ST] = . 1 ;
     the while (! que.empty ()) {
         int U =que.front();
        que.pop();
        if(u==ed)
            return true;
        for(int i=h[u];i!=-1;i=e[i].nxt){
            int v=e[i].v;
            int w=e[i].w;
            if(!depth[v]&&w){
                depth[v]=depth[u]+1;
                que.push(v);
            }
        }
    }
    return false;
}

int dfs(int u,int dis) 
{
    if(u==ed)
        return dis;
    int res=0;
    for(int i=h[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].v;
        int w=e[i].w;
        if((depth[v]==depth[u]+1)&&w)
        {
            int di=dfs(v,min(w,dis-res));
            e[i].w-=di;
            e[i^1].w+=di;
            res+=di;
            if(res==dis)
                return dis;
        }
    }
    return res;
}

int dinic()//dinic求最大流 
{
    int ans=0;
    while(bfs())
    {
        ans+=dfs(st,inf);
    }
    return ans;
}

bool check(int x)
{
    cnt=0;
    memset(h,-1,sizeof(h));
    for( Int I = . 1 ; I <= n-; I ++) // milking machine and cows can connect 
        for ( int J = n-+ . 1 ; J <= n-+ m; J ++ )
             IF (G [I] [J] < = X) 
                the Add (I, J, . 1 );
     for ( int I = . 1 ; I <= n-; I ++) // start point connected milking machine 
        the Add (ST, I, K);
     for ( int I = n-+ . 1 ; I <= n-m +; I ++) // cows even end 
        the Add (I, ED, . 1 );
     int ANS = Dinic ();
     IF (ANS == m)//最大流是奶牛头数 
        return true;
    return false;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n+m;i++)
    {
        for(int j=1;j<=n+m;j++)
        {
            scanf("%d",&g[i][j]);
            if(i!=j&&!g[i][j])
                g[i][j]=inf;
        }
    }
    for(int k=1;k<=n+m;k++)
        for(int i=1;i<=n+m;i++)
            for(int j=1;j<=n+m;j++)
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);            
    st=0,ed=n+m+1;//建起点,终点 
    int l=0,r=inf,mid;
    while(r>=l)
    {
        mid=(r+l)/2;
        if(check(mid))
            r=mid-1;    
        else
            l=mid+1;
    }
    printf("%d\n",l);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/xiongtao/p/11298846.html