多校第一场的题目, 这题很综合, 考察了很多点, 首先对于这种二维平面上带有障碍的最短路在LRJ的白书上有提到, 然后对于后一部分由于城市的占领有顺序所以得到了一个DAG, 然后再二分相邻两点间的最长距离每次用最小路径覆盖判断人数是否小于等于给定人数就可以了。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N = 105;
const double INF = 1e16;
const double eps = 1e-8;
struct Point {
int x, y;
Point (int a= 0, int b = 0) {
x = a, y = b;
}
};
typedef Point Vector;
typedef long long LL;
Vector operator - (Point a, Point b) {
return Vector(a.x - b.x, a.y - b.y);
}
int cross(Vector a, Vector b) {
return a.x * b.y - a.y * b.x;
}
bool intersect(Point a1, Point a2, Point b1, Point b2) {
int c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1),
c3 = cross(b2 - b1, a1 - b1), c4 = cross(b2 - b1, a2 - b1);
return (LL)c1 * c2 < 0 && (LL)c3 * c4 < 0;
}
inline double pow2(int x) {
return (double)x * x;
}
double dist(Point a, Point b) {
return sqrt(pow2(a.x - b.x) + pow2(a.y - b.y));
}
Point A[N], st[N], ed[N];
int ord[N];
double res[N * N];
Point all[N * 3];
double dis[505][505];
const int M = 100005;
struct Match {
struct Edge {
int v;
Edge* next;
void init(int a, Edge* e) {
this->v = a, next = e;
}
};
Edge* it;
Edge* head[N];
Edge E[M];
bool Y[N];
int n, res;
int px[N], py[N];
void init(int n) {
this->n = n;
for(int i = 0; i < n; i++)
head[i] = 0;
fill(px, px + n, -1);
fill(py, py + n, -1);
it = E;
}
void add(int u, int v) {
it->init(v, head[u]);
head[u] = it++;
}
bool find(int u) {
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (!Y[v]) {
Y[v] = 1;
if (py[v] == -1 || find(py[v])) {
py[v] = u;
px[u] = v;
return 1;
}
}
}
return 0;
}
void run() {
res = 0;
for (int i = 0; i < n; i++) {
fill(Y, Y + n, 0);
if (find(i)) res++;
}
}
}G;
int n;
bool jud(double val, int tar) {
G.init(n);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++) {
int u = ord[i], v = ord[j];
if (dis[u][v] < val + eps)
G.add(u, v);
}
G.run();
return n - G.res <= tar;
}
int main() {
int m, p, test;
scanf("%d", &test);
while (test--) {
scanf("%d%d%d", &n, &m, &p);
int tot = 0;
for (int i = 0; i < n; i++) {
scanf("%d%d", &A[i].x, &A[i].y);
all[tot].x = A[i].x, all[tot].y = A[i].y;
tot++;
}
for (int i = 0; i < m; i++) {
scanf("%d%d%d%d", &st[i].x, &st[i].y, &ed[i].x, &ed[i].y);
all[tot].x = st[i].x, all[tot].y = st[i].y;
tot++;
all[tot].x = ed[i].x, all[tot].y = ed[i].y;
tot++;
}
for (int i = 0; i < n; i++) {
scanf("%d", ord + i);
ord[i]--;
}
bool tmp;
for (int i = 0; i < tot; i++)
for (int j = 0; j < tot; j++)
if (i == j)
dis[i][j] = 0;
else
dis[i][j] = INF;
for (int i = 0; i < tot; i++) {
for (int j = i + 1; j < tot; j++) {
tmp = 1;
for (int k = 0; k < m; k++) {
if (intersect(all[i], all[j], st[k], ed[k])) {
tmp = 0;
break;
}
}
if (!tmp) continue;
else {
dis[j][i] = dis[i][j] = min(dist(all[i], all[j]), dis[i][j]);
}
}
}
for (int k = 0; k < tot; k++)
for (int i = 0; i < tot; i++)
for (int j = 0; j < tot; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
int c = 0;
res[c++] = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
res[c++] = dis[i][j];
}
}
sort(res, res + c);
c = unique(res, res + c) - res;
int L = 0, R = c - 1;
while (L <= R) {
int mid = L + R >> 1;
if (jud(res[mid], p))
R = mid - 1;
else
L = mid + 1;
}
printf("%.2lf\n", res[L]);
}
return 0;
}