poj 2112最佳挤奶方案
来源:互联网 发布:在单位混日子 知乎 编辑:程序博客网 时间:2024/04/28 01:36
用FLOYD求出任意两点最小距离,用Dinic求最大流,用二分法搜索最大距离最小值#include <iostream>#include <cstring>#include <cstdio>using namespace std;#define MAX 300#define INF 1000000int dis[MAX][MAX];int map[MAX][MAX];bool sign[MAX][MAX];bool used[MAX];int K,C,n,M;int min(int a,int b){ return a < b ? a : b;}void Build_Graph(int min_max){ int i,j; memset(map,0,sizeof(map)); for(i = K+1; i <=n; i++) //从源点向每头奶牛建一条边,容量为1 map[0][i] = 1; for(i = 1; i <= K; i++) //从取奶器向汇点建边,容量为M map[i][n+1] = M; for(i = K+1;i <= n;i++) //从每头奶牛向取奶器建边,容量为1 { for(j = 1; j <= K;j++){ if(dis[i][j] <= min_max) map[i][j] = 1;} }}bool BFS() //构建层次网络{ memset(used,0,sizeof(used)); memset(sign,0,sizeof(sign)); int queue[100*MAX] = {0}; queue[0] = 0; used[0] = 1; int t = 1,f = 0; while(f < t) { for(int i = 0; i <= n + 1; i++){ if(!used[i] && map[queue[f]][i]) { queue[t++] = i; used[i] = 1; sign[queue[f]][i] = 1; }} f++; } if(used[n+1]) return true; else return false;}int DFS(int v,int sum) //DFS增广{ int i,s,t; if(v == n + 1) return sum; s = sum; for(i = 0; i <= n+1;i++) { if(sign[v][i]){ t = DFS(i,min(map[v][i],sum)); map[v][i] -= t; map[i][v] += t; sum -= t;} } return s-sum;}int main(){ int i,j,k,L,R,mid,ans; cin>>K>>C>>M; n = K + C; for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++){ cin>>dis[i][j]; if(dis[i][j] == 0) dis[i][j] = INF;} } for(k = 1; k <= n; k++) //floyd求最短距离 for(i = 1; i <= n; i++) for(j = 1; j <= n; j++){ dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);} L = 0, R = 10000; while(L < R) //二分搜索 { mid = (L + R)/2; ans = 0; Build_Graph(mid); while(BFS()) ans += DFS(0,INF); //dinic求最大流 if(ans >= C) R = mid; else L = mid + 1; } cout<<R<<endl; return 0;}