It is a basic question based on the graph theory list.
This question was made before the Provincial competition. Now I want to summarize it. I feel that this type of question is classic.
There are cows and machines, and each cow allocates a machine,
There is a distance between the ox and the ox, the ox and the machine, and the machine.
At first, I didn't understand what it was called "The maximum distance and minimum value", that is, C cows and K milk runners. If C cows think of all the milk runners, it takes some distance to go there,
The maximum distance that a cow needs to walk is the maximum value. (DT)
In this way, it would be better to divide the image by two points. If the maximum stream> = C after the mid graph is created, it would be successful.
There are a bunch of points in X, and a bunch of points in Y. If you try to establish a certain relationship from X to Y (such as distance and weight ), after adding the supersource vertex and sink vertex S and T and establishing the corresponding right edge
It is certainly possible to make the points of X and Y belong to the set S and T respectively (this is also the minimum cut idea ).
Ps: Tips for binary output, such as my code if (ans> = mid) R = mid; cout <
A lot of nonsense, just a small reminder of being a weak scum. Add a code.
# Include
# Include
# Include
# Include
# Include
# Include
Using namespace std; const int INF = 0x3c3c3c3c; const int maxn = 500 + 10; // maximum number of nodes struct Edge {// represents a from-> to capacity as cap, the traffic is the arc int from, to, cap, flow ;}; struct Dinic {int n, m, s, t; // number of nodes, edge Number (including reverse arc), Source Vertex, sink vertex vector
Edges; // edge table edge [e] and edge [e ^ 1] are reciprocal arc vectors.
G [maxn]; bool vis [maxn]; int d [maxn]; int cur [maxn]; void AddEdge (int from, int to, int cap) {edges. push_back (Edge) {from, to, cap, 0}); edges. push_back (Edge) {to, from, 0, 0}); int m = edges. size (); G [from]. push_back (m-2); G [to]. push_back m-1);} bool BFS () {memset (vis, 0, sizeof (vis); queue
Q; Q. push (s); d [s] = 0; vis [s] = 1; while (! Q. empty () {int x = Q. front (); Q. pop (); for (int I = 0; I <G [x]. size (); I ++) {Edge & e = edges [G [x] [I]; if (! Vis [e. to] & e. cap> e. flow) {vis [e. to] = 1; d [e. to] = d [x] + 1; Q. push (e. to) ;}}} return vis [t];} int DFS (int x, int a) {if (x = t | a = 0) return; int flow = 0, f; for (int & I = cur [x]; I <G [x]. size (); I ++) {Edge & e = edges [G [x] [I]; if (d [x] + 1 = d [e. to] & (f = DFS (e. to, min (a, e. cap-e.flow)> 0) {e. flow + = f; edges [G [x] [I] ^ 1]. flow-= f; flow + = f; a-= f; if (a = 0) break;} return flow;} int Max Flow (int s, int t) {this-> s = s; this-> t = t; int flow = 0; while (BFS () {memset (cur, 0, sizeof (cur); flow + = DFS (s, INF);} return flow ;}}; int dis [500] [500]; int main () {// freopen ("in.txt", "r", stdin); int K, C, M; while (scanf ("% d", & K, & C, & M) = 3) {int I, j, k, l, a; int sum = K + C; for (I = 1; I <= sum; I ++) {for (j = 1; j <= sum; j ++) {scanf ("% d", & a); if (I = j) {dis [I] [j] = 0; continue;} If (a = 0) dis [I] [j] = INF; else dis [I] [j] = a ;}} for (k = 1; k <= sum; k ++) {for (I = 1; I <= sum; I ++) {for (j = 1; j <= sum; j ++) {if (dis [I] [j]> dis [I] [k] + dis [k] [j]) dis [I] [j] = dis [I] [k] + dis [k] [j] ;}} int L = 1, R = 40000; while (L <R) {int mid = (L + R)/2; Dinic test; for (I = 1; I <= K; I ++) {for (j = K + 1; j <= sum; j ++) {if (dis [I] [j] <= mid) test. addEdge (I, j, 1) ;}} for (I = 1; I <= K; I ++) test. addEdge (0, I, M); for (I = K + 1; I <= sum; I ++) test. addEdge (I, sum + 1, 1); int ans = test. maxflow (0, sum + 1); if (ans> = C) {// why bi_search? It's up R = mid;} else L = mid + 1;} printf ("% d \ n", R);} return 0 ;}