Optimal Milking
//二分枚举最大距离的最小值+Floyd找到最短路+Dinic算法 //参考图论算法书,并对BFS构建层次网络算法进行改进 //Time:157Ms Memory:652K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> using namespace std; #define MAX 250 #define INF 0x3f3f3f3f int K, C, M; int s, t; int d[MAX][MAX]; //各点间最短距离 int res[MAX][MAX]; //残留网络 int lev[MAX]; void build_map(int limit) { memset(res,0,sizeof(res)); for (int i = K + 1; i <= K + C; i++) res[s][i] = 1; for (int i = 1; i <= K; i++) res[i][t] = M; for (int i = K + 1; i <= K + C; i++) for (int j = 1; j <= K; j++) if (d[i][j] <= limit) res[i][j] = 1; } bool bfs() //BFS标记层次网络 { memset(lev, -1, sizeof(lev)); queue<int> q; q.push(s); lev[s] = 0; while (!q.empty()) { //构建层次网络 int cur = q.front(); q.pop(); for(int i = 1; i <= t; i++) { if(lev[i] == -1 && res[cur][i]) //未访问且正向有流量 { q.push(i); lev[i] = lev[cur] + 1; } } } return lev[t] != -1; } int dfs(int v, int alpha) //DFS进行多次增广 { if(v == t || alpha == 0) return alpha; int src = alpha; //原可改进量 for(int i = 1; i <= t; i++) { if(res[v][i] && lev[i] == lev[v] + 1){ //识别下一层次 int tmp = dfs(i, min(alpha, res[v][i])); res[v][i] -= tmp; res[i][v] += tmp; alpha -= tmp; //可改进量减少 } } return src - alpha; //总改进量 } int main() { //freopen("in.txt", "r", stdin); scanf("%d%d%d", &K,&C,&M); s = 0; t = K + C + 1; //源点-汇点 for (int i = 1; i < t; i++) for (int j = 1; j < t; j++) { scanf("%d", &d[i][j]); if (d[i][j] == 0) d[i][j] = INF; } for (int k = 1; k < t; k++) for (int i = 1; i < t; i++) { if (d[i][k] != INF) { for (int j = 1; j < t; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]); } } s = 0; t = K + C + 1; //源点 汇点 int l = 0, r = 9000; while (l < r) { int ans = 0; //到达目的地的奶牛数量 int mid = (l + r) / 2; build_map(mid); while (bfs()) ans += dfs(0,INF); //第二参数指定该点可改进量 ans == C ? r = mid: l = mid+1; } printf("%d\n", r); return 0; }