POJ 2112 Optimal Milking(Floyd+多重匹配+二分枚举)
题意:有K台挤奶机,C头奶牛,每个挤奶机每天只能为M头奶牛服务,下面给的K+C的矩阵,是形容相互之间的距离,求出来走最远的那头奶牛要走多远
输入数据:
第一行三个数 K, C, M
接下来是 (K+C)*(K+C)的矩阵
表示每个物体之间的距离, 0 表示两者之间是不通的。
挤奶机 1, 挤奶机2 .... 挤奶机 K, 奶牛1,奶牛2...奶牛M
题目思路:
对输入进来的数据先进行闭包传递,然后再对奶牛到挤奶机的距离进行二分枚举,枚举出来的值进行多重匹配
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<queue> #include<cmath> using namespace std; #define INF 0x3fffffff #define maxn 1255 int n, m, k;///n个挤奶机 m只奶牛 每台挤奶机最多挤 k只 bool vis[maxn]; int G[maxn][maxn], Dis[100000], DisNum; vector<vector<int> > P;///用来保存匹配的数据 void Floyd() { int len = n + m; DisNum = 0; for(int k=0; k < len; k++) { for(int i=0; i < len; i++) { for(int j=0; j < len; j++) G[i][j] = min(G[i][j], G[i][k]+G[k][j]); } } for(int i=0; i<len; i++) { for(int j=0; j<len; j++) Dis[DisNum ++] = G[i][j]; } } bool Find(int u,int limt) { for(int i=0; i<n; i++) { if(!vis[i] && G[u][i] <= limt) { vis[i] = true; if(P[i].size() < k) { P[i].push_back(u); return true; } for(int j=0; j<P[i].size(); j++) { if( Find(P[i][j], limt) ) { P[i].erase(P[i].begin()+j); P[i].push_back(u); return true; } } } } return false; } bool solve(int limt) { P.clear(); P.resize(n+1); for(int i=n; i<n+m; i++) { memset(vis, false, sizeof(vis)); if( !Find(i,limt) ) return false; } return true; } int main() { while(scanf("%d %d %d", &n, &m, &k) != EOF) { for(int i=0; i<n+m; i++) { for(int j=0; j<n+m; j++) { scanf("%d", &G[i][j]); if(!G[i][j]) G[i][j] = INF; } } Floyd();///先进行一下闭包传递 sort(Dis,Dis + DisNum); int L = 0, R = DisNum - 1; while(L < R) { int mid = (L + R) / 2; if( solve(Dis[mid]) ) R = mid; else L = mid + 1; } printf("%d\n", Dis[R]); } return 0; }