【题目链接】 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\n",ans); } int main(){ while(~scanf("%d%d%d",&K,&C,&M)){ init(); solve(); }return 0; }
POJ 2112 Optimal Milking(二分图匹配)
原文:http://www.cnblogs.com/forever97/p/poj2112.html