The question is as follows:
In a two-dimensional coordinate system, there are n cities and the coordinates are given, and then p soldiers are going to occupy the n cities, but there are m roadblocks on the road, all of which are line segments, soldiers are not allowed to move forward beyond the roadblock.
Every soldier has a grain bag of the same size, and he can fill his own grain bags in every city. Walking in the middle consumes a unit of dry food.
The question is how much is the minimum capacity of these grain bags, provided that p soldiers can occupy the n cities. The order of city occupation is also a good question and must be observed.
Idea: P soldiers occupy n cities. It can be seen that p soldiers walk out of the p path and cover all the points. But the question does not require every soldier to take the title. That is, as long as the minimum path coverage is less than or equal to p, it means that all cities can be occupied by p soldiers.
One of the requirements for minimum path coverage is directed and without loops. In this case, the city must be ranked in order.
This is in line with a topological sequence. Therefore, the minimum path overwrite can be performed.
The overall step is to calculate the distance between points at the beginning. Because of the obstacles, you must add the two endpoints of these line segments to the point set for calculation, when the two points are pre-processed, it depends on whether there is a line block between the two points. When the two points are blocked, they are first calculated based on the non-endpoint. Note that when the line segment is handed over, do not worry about the intersection of the endpoint, because it can still pass. The distance is calculated based on the straight line. Then floyd processed it and the distance between any two points was reached.
After calculation, we need the capacity of the dry grain bag. The general method is to calculate the feasibility in two ways.
For a binary value, we create a graph, and the distance between any two points is not greater than this value to connect the edge.
Of course, we pay attention to the order of occupation given in the question. The front side can be connected to the back side, but not the opposite.
Then overwrite the path. Determine whether it is feasible
# Include <iostream> # include <cstdio> # include <algorithm> # include <cstring> # include <cmath> # include <map> # include <queue> # include <set> # include <vector> # define eps 1e-8 # define MAXN 333 # define INF 1111111111 using namespace std; typedef double TYPE; struct POINT {TYPE x; TYPE y; POINT (): x (0), y (0) {}; POINT (TYPE _ x _, TYPE _ y _): x (_ x _), y (_ y _) {}; bool operator == (const POINT & p) const {return (fabs (X-p. x) <eps & fabs (y-p. y) <eps) ;}} p [MAXN]; TYPE Distance (const POINT & a, const POINT & B) {return sqrt (. x-B. x) * (. x-B. x) + (. y-B. y) * (. y-B. y);} struct SEG {POINT a; // start POINT B; // end point seg () {}; SEG (POINT _ a _, POINT _ B _): a (_ a _), B (_ B _) {}; bool operator == (const SEG & p) const {return (p. a = a & p. B = B) | (p. B = a & p. a = B) ;}} seg [MAXN]; TYPE Cross (const POINT & a, con St POINT & B, const POINT & o) {return (. x-o. x) * (B. y-o. y)-(B. x-o. x) * (. y-o. y);} bool IsIntersect (const SEG & u, const SEG & v) {return (Cross (v. a, u. b, u. a) * Cross (u. b, v. b, u. a)> 0) & (Cross (u. a, v. b, v. a) * Cross (v. b, u. b, v. a)> 0) & (max (u. a. x, u. b. x)> min (v. a. x, v. b. x) & (max (v. a. x, v. b. x)> min (u. a. x, u. b. x) & (max (u. a. y, u. b. y)> min (v. a. y, v. b. y) & (max (v. a. y, v. b. Y)> min (u. a. y, u. b. y);} int seq [MAXN]; struct node {int v, next;} edge [MAXN * MAXN]; int e, head [MAXN], mark [MAXN], cx [MAXN], cy [MAXN], n, m, so; double dis [MAXN] [MAXN]; void insert (int x, int y) {edge [e]. v = y; edge [e]. next = head [x]; head [x] = e ++;} int path (int u) {for (int I = head [u]; I! =-1; I = edge [I]. next) {int v = edge [I]. v; if (! Mark [v]) {mark [v] = 1; if (cy [v] =-1 | path (cy [v]) {cx [u] = v; cy [v] = u; return 1 ;}}return 0 ;}int gao () {int ans = 0; memset (cx, -1, sizeof (cx); memset (cy,-1, sizeof (cy); for (int I = 1; I <= n; I ++) {memset (mark, 0, sizeof (mark); ans + = path (I);} return ans;} void floyd (int n) {for (int k = 1; k <= n; k ++) for (int I = 1; I <= n; I ++) for (int j = 1; j <= n; j ++) if (dis [I] [k] + dis [k] [j] <dis [I] [j]) dis [I] [j] = dis [I] [k] + dis [k] [j];} bool OK (double mid) {e = 0; memset (head, -1, sizeof (head); for (int I = 1; I <= n; I ++) for (int j = I + 1; j <= n; j ++) if (dis [seq [I] [seq [j] <= mid) insert (seq [I], seq [j] + n ); int x = gao (); if (n-x <= so) return true; return false;} void slove () {double l = 0, r = INF; double ans =-1; while (r-l> eps) {double mid = (l + r)/2; if (OK (mid) {ans = mid; r = mid;} else l = mid;} printf ("%. 2f \ n ", ans);} int main () {int T; scanf (" % d ", & T); while (T --) {scanf ("% d", & n, & m, & so); for (int I = 1; I <= n; I ++) scanf ("% lf", & p [I]. x, & p [I]. y); for (int I = 1; I <= m; I ++) {scanf ("% lf", & seg [I]. a. x, & seg [I]. a. y, & seg [I]. b. x, & seg [I]. b. y); p [n + I * 2-1] = seg [I]. a; p [n + I * 2] = seg [I]. B ;}for (int I = 1; I <= n; I ++) scanf ("% d", & seq [I]); for (int I = 1; I <= n + m * 2; I ++) for (int j = 1; j <= n + m * 2; j ++) {if (I = j) {dis [I] [j] = 0; continue;} int flag = false; for (int k = 1; k <= m; k ++) {if (seg [k] = SEG (p [I], p [j]) continue; if (IsIntersect (seg [k], SEG (p [I], p [j]) {flag = true; break;} if (flag) dis [I] [j] = INF; else dis [I] [j] = Distance (p [I], p [j]);} floyd (n + m * 2); slove ();} return 0 ;}