POJ 2112 Optimal Milking(二分图匹配)

【题目链接】 http://poj.org/problem?id=2112

【题目大意】

  给出一些挤奶器,每台只能供给M头牛用,牛和挤奶器之间有一定的距离
  现在要让每头牛都挤奶,同时最小化牛到挤奶器的距离,求最小距离

【题解】

  首先用floyd计算出牛和挤奶器之间的距离,
  我们二分最小答案,然后利用二分图检验是否可行,对于M匹配这个条件可以将挤奶器拆点。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> 
using namespace std;
const int MAX_V=1000;
const int INF=0x3f3f3f3f;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
bool dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i],w=match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v]=u;
            match[u]=v;
            return 1;
        }
    }return 0;
}
int bipartite_matching(){
    int res=0;
    memset(match,-1,sizeof(match));
    for(int v=0;v<V;v++){
        if(match[v]<0){
            memset(used,0,sizeof(used));
            if(dfs(v))res++;
        }
    }return res;
}
const int MAX_N=240;
int K,C,M;
int mp[MAX_N][MAX_N];
void construct_graph(int lim){
    V=C+K*M;
    for(int i=0;i<=V;i++)G[i].clear();
    for(int i=1;i<=C;i++){
        for(int j=1;j<=K;j++){
            if(mp[K+i][j]<=lim){
                for(int t=1;t<=M;t++){
                    add_edge(i,C+(j-1)*M+t);
                }
            }
        }
    }
}
int init(){
    for(int i=1;i<=K+C;i++)
    for(int j=1;j<=K+C;j++){
        scanf("%d",&mp[i][j]);
        if(mp[i][j]==0)mp[i][j]=INF;
    }
    for(int k=1;k<=K+C;k++)
        for(int i=1;i<=K+C;i++)
            for(int j=1;j<=K+C;j++)
                mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
}
void solve(){
    int ans=1,l=1,r=200*(K+C);
    while(l<=r){
        int mid=(l+r)>>1;
        construct_graph(mid);
        if(bipartite_matching()==C)ans=mid,r=mid-1;
        else l=mid+1;
    }printf("%d
",ans);
}
int main(){
     while(~scanf("%d%d%d",&K,&C,&M)){
         init();
         solve();
     }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/poj2112.html