Problem:
Repairing
In the International City of Pipe Construction, it is planned to repair the water pipe at a certain point in the water pipe network.
The network consists of water pipe segments, stop valves and source point.
A water pipe is represented by a segment on a 2D-plane and intersected pair of water pipe segments are connected at the intersection point.
A stop valve, which prevents from water flowing into the repairing point while repairing,  is represented by a point on some water pipe segment.
In the network, just one source point exists and water is supplied to the network from this point.
Of course, while repairing, we have to stop water supply in some areas, but,
in order to reduce the risk of riots, the length of water pipes stopping water supply must be minimized.
What you have to do is to write a program to minimize the length of water pipes needed to stop water supply when the coordinates of end points of water pipe segments, stop valves, source point and repairing point are given.
Input
A data set has the following format:
N
M
x
s1
y
s1
x
d1
y
d1
...
x
sN
y
sN
x
dN
y
dN
x
v1
y
v1
...
x
vM
y
vM
x
b
y
b
x
c
y
c
The first line of the input contains two integers,
N
(
1 ≤ N ≤ 300
) and
M
(
0 ≤ M ≤ 1,000
) that indicate the number of water pipe segments and stop valves.
The following
N
lines describe the end points of water pipe segments.
The
i
-th line contains four integers,
x
si
,
y
si
,
x
di
and
y
di
that indicate the pair of coordinates of end points of
i
-th water pipe segment.
The following
M
lines describe the points of stop valves.
The
i
-th line contains two integers,
x
vi
and
y
vi
that indicate the coordinate of end points of
i
-th stop valve.
The following line contains two integers,
x
b
and
y
b
that indicate the coordinate of the source point.
The last line contains two integers,
x
c
and
y
c
that indicate the coordinate of the repairing point.
You may assume that any absolute values of coordinate integers are less than 1,000 (inclusive.) 
You may also assume each of the stop valves, the source point and the repairing point is always on one of water pipe segments and that that each pair among the stop valves, the source point and the repairing point are different.
And, there is not more than one intersection between each pair of water pipe segments.
Finally, the water pipe network is connected, that is, all the water pipes are received water supply initially.
Output
Print the minimal length of water pipes needed to stop water supply in a line.
The absolute or relative error should be less than or
10
-6
.
When you cannot stop water supply to the repairing point even though you close all stop valves, print "
-1
" in a line.
Sample Input 1
1 2
0 0 10 0
1 0
9 0
0 0
5 0
Output for the Sample Input 1
9.0
Sample Input 2
5 3
0 4 2 4
0 2 2 2
0 0 2 0
0 0 0 4
2 0 2 4
0 2
1 0
2 2
1 4
2 1
Output for the Sample Input 2
3.0
Sample Input 3
2 1
0 0 0 4
0 2 2 2
1 2
0 1
0 3
Output for the Sample Input 3
-1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int N = 222222;
const long double eps = 1e-8;

int sign(const long double &x) {
	return x < -eps ? -1 : x > eps;
}

struct Point {
	long double x, y;
	Point() {}
	Point(long double x, long double y) : x(x), y(y) {}
	
	Point operator - (const Point &other) const {
		return Point(x - other.x, y - other.y);
	} 
	Point operator + (const Point &other) const {
		return Point(x + other.x, y + other.y);
	}
	Point operator * (const long double &t) const {
		return Point(x * t, y * t);
	}
	bool operator < (const Point &other) const {
		if (sign(x - other.x) == 0) {
			return y < other.y;
		} else {
			return x < other.x;
		}
	}
	bool operator == (const Point &other) const {
		return (sign(x - other.x) == 0) && (sign(y - other.y) == 0);
	}
	
	void read() {
		double xx, yy;
		scanf("%lf%lf", &xx, &yy);
		x = xx;
		y = yy;
	}
	void print() {
		cout << x << " " << y << endl;
	}
};
long double dist(const Point &a, const Point &b) {
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
long double det(const Point &a, const Point &b) {
	return a.x * b.y - a.y * b.x;
}

long double dot(const Point &a, const Point &b) {
	return a.x * b.x + a.y * b.y;
}

bool parallel(const pair<Point, Point> &l1, const pair<Point, Point> &l2) {
	return sign(det(l1.first - l1.second, l2.first - l2.second)) == 0;
}

bool PointOnSegment(const Point &p, const Point &a, const Point &b) {
	return sign(det(p - a, p - b)) == 0 && sign(dot(p - a, p - b)) <= 0;
}

Point intersection(Point P, Point v, Point Q, Point w) {
	Point u = P - Q;
	long double t = det(w, u) / det(v, w);
	return P + v * t;
}

Point stdPoint; 
Point vertex[N * 2];
bool vis[N * 2], visedge[N * 2], ban[N * 2], open[N * 2];
int nxt[N * 2], to[N * 2], edgelist[N];
int n, m, vertices, tot;


void add(int u, int v) {
	nxt[tot] = edgelist[u];	
	to[tot] = v;
	edgelist[u] = tot++;
}
void bfs1(int start) {
	vector<int> queue;
	queue.push_back(start);
	memset(vis, 0, sizeof vis);
	memset(open, 0, sizeof open);
	vis[start] = 1;
	for (int head = 0; head < (int)queue.size(); head++) {
		int t = queue[head];
		if (ban[t]) {
			open[t] = 1;
			continue;
		}
		for (int p = edgelist[t]; p != -1; p = nxt[p]) {
			if (!vis[to[p]]) {
				vis[to[p]] = 1;
				queue.push_back(to[p]);
			}
		}
	}
}

long double bfs2(int start, int fin) {
	vector<int> queue;
	queue.push_back(start);
	memset(vis, 0, sizeof vis);
	memset(visedge, 0, sizeof visedge);
	vis[start] = 1;
	long double ret = 0;
	for (int head = 0; head < (int)queue.size(); head++) {
		int t = queue[head];
		if (t == fin) {
			return -1e10;
		}
		if (ban[t] && open[t]) {
			continue;
		}
		for (int p = edgelist[t]; p != -1; p = nxt[p]) {
			if (!visedge[p]) {
				ret += dist(vertex[t], vertex[to[p]]);
				visedge[p] = visedge[p ^ 1] = 1;
			}
			if (!vis[to[p]]) {
				vis[to[p]] = 1;
				queue.push_back(to[p]);
			}
		}	
	}
	//cout << endl;
	return ret;
}

bool cmp(int a, int b) {
	return dist(vertex[a], stdPoint) < dist(vertex[b], stdPoint);
}

int main() {
	scanf("%d%d", &n, &m);
	
	vector<pair<Point, Point> > pipe;
	
	map<Point, int> id; 
	vector<int> keyPoint[N];
	vertices = 0;
	for (int i = 1; i <= n; i++) {
		Point u, v;
		u.read();
		v.read();
		if (id.count(u) == 0) {
			//cout << "111" << endl;
			id[u] = ++vertices;
			vertex[vertices] = u;
		}
		if (id.count(v) == 0) {
			id[v] = ++vertices;
			vertex[vertices] = v;
		}
		pipe.push_back(make_pair(u, v));
		keyPoint[i - 1].push_back(id[u]);
		keyPoint[i - 1].push_back(id[v]);
		//u.print(); v.print();
		//cout << vertices << endl;
	}
		
	for (int i = 1; i <= m; i++) {
		Point t;
		t.read();
		if (id.count(t) == 0) {
			id[t] = ++vertices;
			vertex[vertices] = t;
		}
		ban[id[t]] = true;
		for (int j = 0; j < (int)pipe.size(); j++) {
			if (PointOnSegment(t, pipe[j].first, pipe[j].second)) {
				keyPoint[j].push_back(id[t]);
			}
		}
	}
	
	Point sourcePoint, targetPoint;
	sourcePoint.read();
	targetPoint.read();
	
	for (int i = 0; i < (int)pipe.size(); i++) {
		for (int j = 0; j < (int)pipe.size(); j++) {
			if (i != j) {
				if (!parallel(pipe[i], pipe[j])) {
					Point crs = intersection(pipe[i].first, pipe[i].second - pipe[i].first, pipe[j].first, pipe[j].second - pipe[j].first);
					if (PointOnSegment(crs, pipe[i].first, pipe[i].second) && PointOnSegment(crs, pipe[j].first, pipe[j].second)) {
						if (id.count(crs) == 0) {
							id[crs] = ++vertices;
							vertex[vertices] = crs;
						}
						keyPoint[i].push_back(id[crs]);
						keyPoint[j].push_back(id[crs]);
					}
				}
			}
		}
	}	
	
	bool flagS, flagT;
	int source, target;
	//cout << "sz = " << keyPoint[0][0] << " " << keyPoint[0][1]  << endl;
	flagS = flagT = false;
	if (id.count(sourcePoint) == 0) {
		id[sourcePoint] = ++vertices;
		vertex[vertices] = sourcePoint;
		flagS = true;
	}
	source = id[sourcePoint];
	if (id.count(targetPoint) == 0) {
		id[targetPoint] = ++vertices;
		vertex[vertices] = targetPoint;
		flagT = true;
	}
	target = id[targetPoint];
	
	for (int i = 0; i < (int)pipe.size(); i++) {
		if (flagS && PointOnSegment(sourcePoint, pipe[i].first, pipe[i].second)) {
			keyPoint[i].push_back(source);
		}
		if (flagT && PointOnSegment(targetPoint, pipe[i].first, pipe[i].second)) {
			keyPoint[i].push_back(target);
		}
	}
	
	memset(edgelist, -1, sizeof edgelist);
	for (int i = 0; i < (int)pipe.size(); i++) {
		stdPoint = pipe[i].first;
		sort(keyPoint[i].begin(), keyPoint[i].end(), cmp);
		keyPoint[i].erase(unique(keyPoint[i].begin(), keyPoint[i].end()), keyPoint[i].end());
		for (int j = 0; j < (int)keyPoint[i].size() - 1; j++) {
			add(keyPoint[i][j], keyPoint[i][j + 1]);
			add(keyPoint[i][j + 1], keyPoint[i][j]);
		}
	}
	
	/*cout << vertices << endl;
	for (int i = 1; i <= vertices; i++) {
		vertex[i].print();
	}*/
	/*for (int i = 1; i <= vertices; i++) {
		cout << i << " : ";
		vertex[i].print();
	}*/
	long double sumLength = bfs2(source, -1);
	bfs1(target);
/*	for (int i = 1; i <= vertices; i++) {
		cout << ban[i] << " " << open[i] << endl;
	}*/

	long double answer = bfs2(source, target);
	if (answer > -1) {
		printf("%.8f\n", (double)(sumLength - answer));
	} else {
		puts("-1");
	}
	
		
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 18376
final_rank: 10

code_snippet: #line 1 "a.cpp"
/*	author:  Kite_kuma
	created: 2022.07.07 11:44:43 */

#line 2 "SPJ-Library/geometry/geometry.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>

using R = long double;
using point = std::complex<R>;
using arrow = point;
const R EPS(1e-10), PI(acosl(-1));

inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; }
inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; }
/*
	sign of x
	-1: x < 0
	 0: x == 0
	 1: x > 0
*/
inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
/*
	sign of (a-b)
	-1: a < b
	 0: a == b
	 1: a > b
*/
inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

std::istream &operator>>(std::istream &is, point &p) {
	R a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; }

// rotate point 'p' for counter clockwise direction
point rotate(const point &p, const R &theta) {
	return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag());
}

R radian_to_degree(const R &r) { return (r * 180.0 / PI); }
R degree_to_radian(const R &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
R get_angle(const point &a, const point &b, const point &c) {
	const point v(a - b), w(c - b);
	R theta = fabsl(atan2l(w.imag(), w.real()) - atan2l(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const point &a, const point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct segment;
struct line {
	point a, b;
	line() = default;
	line(const point &a, const point &b) : a(a), b(b) {}
	// Ax + By + C = 0
	line(const R &A, const R &B, const R &C) {
		if(eq(A, 0)) {
			assert(!eq(B, 0));
			a = point(0, -C / B), b = point(1, -(A + C) / B);
		} else {
			a = point(-C / A, 0), b = point(-(B + C) / A, 1);
		}
	}
	explicit line(const segment &seg);
	friend std::ostream &operator<<(std::ostream &os, line &ln) { return os << '(' << ln.a << " -- " << ln.b << ')'; }
	friend std::istream &operator>>(std::istream &is, line &a) { return is >> a.a >> a.b; }
};
struct segment {
	point a, b;
	segment() = default;
	segment(const point &a, const point &b) : a(a), b(b) {}
	explicit segment(const line &ln) : a(ln.a), b(ln.b) {}
	friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; }
	friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; }
};
line::line(const segment &seg) : a(seg.a), b(seg.b) {}

struct circle {
	point center;
	R radius;
	circle() = default;
	circle(const point &center, const R &radius) : center(center), radius(radius) {}
};

using points = std::vector<point>;
using polygon = std::vector<point>;
using segments = std::vector<segment>;
using lines = std::vector<line>;
using circles = std::vector<circle>;

R cross(const point &a, const point &b) { return real(a) * imag(b) - imag(a) * real(b); }
R dot(const point &a, const point &b) { return real(a) * real(b) + imag(a) * imag(b); }

enum CCW {
	ONLINE_FRONT = -2,
	CLOCKWISE = -1,
	ON_SEGMENT = 0,
	COUNTER_CLOCKWISE = 1,
	ONLINE_BACK = 2,
};
int ccw(const point &a, point b, point c) {
	b -= a, c -= a;
	const R crs_b_c = cross(b, c);
	if(crs_b_c > EPS) return CCW::COUNTER_CLOCKWISE;
	if(crs_b_c < -EPS) return CCW::CLOCKWISE;
	if(dot(b, c) < -EPS) return CCW::ONLINE_BACK;
	if(norm(b) + EPS < norm(c)) return CCW::ONLINE_FRONT;
	return CCW::ON_SEGMENT;
}

bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); }
bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }

bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); }
bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }

point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); }
point projection(const segment &s, const point &p) { return projection(line(s), p); }

point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; }
point reflection(const segment &s, const point &p) { return projection(line(s), p); }

R distance(const point &p, const point &q);
R distance(const line &l, const point &p);
int number_of_common_tangents(const circle &c1, const circle &c2) {
	const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
}

// number of common points (-1: infinite)
int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }
int intersect(const point &p, const line &l) { return intersect(l, p); }
int intersect(const line &l, const line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(!parallel(l, m));
}
int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); }
int intersect(const point &p, const segment &s) { return intersect(s, p); }
int intersect(const line &l, const segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1;
}
int intersect(const segment &s, const line &l) { return intersect(l, s); }
int intersect(const circle &c, const line &l) {
	R d = c.radius - distance(l, c.center);
	return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0;
}
int intersect(const line &l, const circle &c) { return intersect(c, l); }
int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); }
int intersect(const point &p, const circle &c) { return intersect(c, p); }
int intersect(const segment &s, const segment &t) {
	if(same_point(s.a, s.b)) return intersect(t, s.a);
	if(intersect(line(s), t.a) && intersect(line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}
int intersect(const circle &c, const segment &s) {
	const point h = projection(s, c.center);
	const int c0 = compare(distance(h, c.center), c.radius);
	if(c0 == 1) return 0;
	if(c0 == 0) return intersect(s, h);
	const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius);
	if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0);
	return intersect(s, h) ? 2 : 0;
}
int intersect(const segment &s, const circle &c) { return intersect(c, s); }
int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

// distance of two shaps
R distance(const point &a, const point &b) { return fabs(a - b); }
R distance(const line &l, const point &p) { return distance(p, projection(l, p)); }
R distance(const point &p, const line &l) { return distance(l, p); }
R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; }
R distance(const segment &s, const point &p) {
	const point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p));
}
R distance(const point &p, const segment &s) { return distance(s, p); }
R distance(const segment &a, const segment &b) {
	if(intersect(a, b)) return R(0);
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}
R distance(const line &l, const segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}
R distance(const segment &s, const line &l) { return distance(l, s); }
R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); }
R distance(const point &p, const circle &c) { return distance(c, p); }
R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); }
R distance(const line &l, const circle &c) { return distance(c, l); }
R distance(const circle &c1, const circle &c2) {
	const R d = distance(c1.center, c2.center);
	if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius;
	if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d;
	return R(0);
}
R distance(const circle &c, const segment &s) {
	const point p = projection(s, c.center);
	const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b));
	if(dist_min > c.radius) return dist_min - c.radius;
	const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b));
	return dist_max < c.radius ? c.radius - dist_max : R(0);
}
R distance(const segment &s, const circle &c) { return distance(c, s); }

point crosspoint(const line &l, const line &m) {
	R A = cross(l.b - l.a, m.b - m.a);
	R B = cross(l.b - l.a, l.b - m.a);
	if(eq(A, 0.)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}
point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); }
point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); }
point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); }
#line 4 "SPJ-Library/graph/graph.hpp"
#include <deque>
#include <iostream>
#include <queue>
#include <tuple>
#line 9 "SPJ-Library/graph/graph.hpp"

#pragma region graph

template <class cost_type = long long>
class graph {
   public:
	struct edge {
	   public:
		int from, to;
		cost_type cost;
		int id;
		edge() = default;
		edge(int from_, int to_, cost_type cost_ = 1, int id_ = -1) : from(from_), to(to_), cost(cost_), id(id_) {}
		bool operator<(const edge &a) const { return cost < a.cost; }
		bool operator>(const edge &a) const { return cost > a.cost; }
		friend std::ostream &operator<<(std::ostream &s, const edge &a) {
			s << '(' << a.from << " -> " << a.to << "), cost: " << a.cost << ", id: " << a.id;
			return s;
		}
	};

   private:
	std::vector<std::vector<edge>> edges;
	int next_edge_id = 0;

   public:
	inline const std::vector<edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<edge> &operator[](int k) { return edges[k]; }

	int size() const { return int(edges.size()); }
	void resize(const int n) { edges.resize(n); }
	int edge_count() const { return next_edge_id; }

	friend std::ostream &operator<<(std::ostream &s, const graph<cost_type> &g) {
		for(const auto &adj : g.edges)
			for(const auto &ed : adj) s << ed << '\n';
		return s;
	}

	graph() = default;
	graph(int n) : edges(n) {}
	graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const cost_type INF = std::numeric_limits<cost_type>::max() / 3;

	void input(int e = -1, bool weight = false, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			std::cin >> u >> v;
			cost_type cost = 1;
			if(weight) std::cin >> cost;
			add_edge(u, v, cost, directed, idx);
		}
	}

	inline int add_edge(int u, int v, cost_type cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(u, v, cost, next_edge_id);
		if(!directed && u != v) edges[v].emplace_back(v, u, cost, next_edge_id);
		return next_edge_id++;
	}
};
#pragma endregion
#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 7 "SPJ-Library/template/basic_func.hpp"

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 7 "a.cpp"

point rot(const point& p) { return rotate(p, 0.0001); }

R solve(int pipe_number) {
	int valve_number;
	cin >> valve_number;
	segments pipes;
	points pts;
	vector<int> left(pipe_number), right(pipe_number);
	R ret = 0.;
	rep(i, pipe_number) {
		point s, t;
		cin >> s >> t;
		s = rot(s);
		t = rot(t);
		if(t < s) swap(s, t);
		ret += distance(s, t);
		pipes.emplace_back(s, t);
		// left[i] = (int)pts.size();
		// // pts.push_back(s);
		// right[i] = int(pts.size());
		// // pts.push_back(t);
	}
	vvi crs(pipe_number, vi(pipe_number, -1));
	vector<vi> on_points(pipe_number);
	rep(i, pipe_number) rep(j, i + 1, pipe_number) {
		const segment& segi = pipes[i];
		const segment& segj = pipes[j];
		if(intersect(segi, segj)) {
			crs[i][j] = crs[j][i] = int(pts.size());
			point crspt = crosspoint(segi, segj);
			pts.push_back(crspt);
			on_points[i].push_back(crs[i][j]);
			on_points[j].push_back(crs[i][j]);
		}
	}
	vector<int> valve_id(valve_number + 2);

	auto set_id = [&](const point& p) -> int {
		int setid;
		vector<int> crosses;
		rep(pipeid, pipe_number) {
			if(intersect(p, pipes[pipeid])) {
				crosses.push_back(pipeid);
			}
		}
		assert(int(crosses.size()) <= 2 && crosses.size());
		if(crosses.size() == 1) {
			setid = (int)pts.size();
			pts.push_back(p);
			foa(pipeid, crosses) { on_points[pipeid].push_back(setid); }
		} else {
			setid = crs[crosses.front()][crosses.back()];
		}
		return setid;
	};

	foa(setid, valve_id) {
		point valve;
		cin >> valve;
		valve = rot(valve);
		setid = set_id(valve);
	}

	rep(i, pipe_number) { left[i] = set_id(pipes[i].a); }
	rep(i, pipe_number) { right[i] = set_id(pipes[i].b); }

	const int source = valve_id[valve_number];
	const int repair = valve_id[valve_number + 1];
	graph<R> g(int(pts.size()));

	rep(i, pipe_number) {
		vector<int>& ids = on_points[i];
		sort(all(ids), [&pts](int ii, int j) { return pts[ii] < pts[j]; });
		// ids.push_back(right[i]);
		// ids.insert(ids.begin(), left[i]);
		debug(i, ids);

		rep(j, int(ids.size()) - 1) {
			int from = ids[j];
			int to = ids[j + 1];
			g.add_edge(from, to, distance(pts[from], pts[to]), false, 0);
			// debug(from, to);
		}
	}

	vector<int> point_id_to_valve_id(int(pts.size()), -1);
	rep(i, valve_number) point_id_to_valve_id[valve_id[i]] = i;
	vector<int> closed(int(pts.size())), visited(int(pts.size()));

	queue<int> q;
	q.push(repair);
	visited[repair] = 1;
	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(nxt, g[now]) {
			debug(now, nxt.to);
			if(visited[nxt.to]) continue;
			const int vid = point_id_to_valve_id[nxt.to];
			if(vid != -1) closed[nxt.to] = 1;
			if(!closed[nxt.to]) {
				q.push(nxt.to);
				visited[nxt.to] = 1;
			}
		}
	}
	if(visited[source]) return -2;

	q.push(source);
	visited.assign(int(pts.size()), 0);
	visited[source] = 1;

	debug(closed, pts);

	set<int> reduced_ids;

	while(q.size()) {
		int now = q.front();
		q.pop();

		foa(e, g[now]) {
			if(!reduced_ids.count(e.id)) {
				ret -= e.cost;
				debug(e.from, e.to, e.cost, e.id);
				reduced_ids.insert(e.id);
			}
			if(!visited[e.to] && !closed[e.to]) {
				q.push(e.to);
				visited[e.to] = 1;
			}
		}
	}

	return ret;
}

int main() {
	int pipe_number;
	while(cin >> pipe_number && pipe_number) {
		R ans = solve(pipe_number);
		if(ans < -1)
			print(-1);
		else
			print(ans);
	}
}
accuracy: 1
time_ms: 20
memory_kb: 8420
final_rank: 7

code_snippet: #line 1 "a.cpp"
/*	author:  Kite_kuma
	created: 2022.07.07 11:44:43 */

#line 2 "SPJ-Library/geometry/geometry.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>

using R = long double;
using point = std::complex<R>;
using arrow = point;
const R EPS(1e-10), PI(acosl(-1));

inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; }
inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; }
/*
	sign of x
	-1: x < 0
	 0: x == 0
	 1: x > 0
*/
inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
/*
	sign of (a-b)
	-1: a < b
	 0: a == b
	 1: a > b
*/
inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

std::istream &operator>>(std::istream &is, point &p) {
	R a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; }

// rotate point 'p' for counter clockwise direction
point rotate(const point &p, const R &theta) {
	return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag());
}

R radian_to_degree(const R &r) { return (r * 180.0 / PI); }
R degree_to_radian(const R &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
R get_angle(const point &a, const point &b, const point &c) {
	const point v(a - b), w(c - b);
	R theta = fabsl(atan2l(w.imag(), w.real()) - atan2l(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const point &a, const point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct segment;
struct line {
	point a, b;
	line() = default;
	line(const point &a, const point &b) : a(a), b(b) {}
	// Ax + By + C = 0
	line(const R &A, const R &B, const R &C) {
		if(eq(A, 0)) {
			assert(!eq(B, 0));
			a = point(0, -C / B), b = point(1, -(A + C) / B);
		} else {
			a = point(-C / A, 0), b = point(-(B + C) / A, 1);
		}
	}
	explicit line(const segment &seg);
	friend std::ostream &operator<<(std::ostream &os, line &ln) { return os << '(' << ln.a << " -- " << ln.b << ')'; }
	friend std::istream &operator>>(std::istream &is, line &a) { return is >> a.a >> a.b; }
};
struct segment {
	point a, b;
	segment() = default;
	segment(const point &a, const point &b) : a(a), b(b) {}
	explicit segment(const line &ln) : a(ln.a), b(ln.b) {}
	friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; }
	friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; }
};
line::line(const segment &seg) : a(seg.a), b(seg.b) {}

struct circle {
	point center;
	R radius;
	circle() = default;
	circle(const point &center, const R &radius) : center(center), radius(radius) {}
};

using points = std::vector<point>;
using polygon = std::vector<point>;
using segments = std::vector<segment>;
using lines = std::vector<line>;
using circles = std::vector<circle>;

R cross(const point &a, const point &b) { return real(a) * imag(b) - imag(a) * real(b); }
R dot(const point &a, const point &b) { return real(a) * real(b) + imag(a) * imag(b); }

enum CCW {
	ONLINE_FRONT = -2,
	CLOCKWISE = -1,
	ON_SEGMENT = 0,
	COUNTER_CLOCKWISE = 1,
	ONLINE_BACK = 2,
};
int ccw(const point &a, point b, point c) {
	b -= a, c -= a;
	const R crs_b_c = cross(b, c);
	if(crs_b_c > EPS) return CCW::COUNTER_CLOCKWISE;
	if(crs_b_c < -EPS) return CCW::CLOCKWISE;
	if(dot(b, c) < -EPS) return CCW::ONLINE_BACK;
	if(norm(b) + EPS < norm(c)) return CCW::ONLINE_FRONT;
	return CCW::ON_SEGMENT;
}

bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); }
bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }

bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); }
bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }

point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); }
point projection(const segment &s, const point &p) { return projection(line(s), p); }

point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; }
point reflection(const segment &s, const point &p) { return projection(line(s), p); }

R distance(const point &p, const point &q);
R distance(const line &l, const point &p);
int number_of_common_tangents(const circle &c1, const circle &c2) {
	const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
}

// number of common points (-1: infinite)
int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }
int intersect(const point &p, const line &l) { return intersect(l, p); }
int intersect(const line &l, const line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(!parallel(l, m));
}
int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); }
int intersect(const point &p, const segment &s) { return intersect(s, p); }
int intersect(const line &l, const segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1;
}
int intersect(const segment &s, const line &l) { return intersect(l, s); }
int intersect(const circle &c, const line &l) {
	R d = c.radius - distance(l, c.center);
	return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0;
}
int intersect(const line &l, const circle &c) { return intersect(c, l); }
int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); }
int intersect(const point &p, const circle &c) { return intersect(c, p); }
int intersect(const segment &s, const segment &t) {
	if(same_point(s.a, s.b)) return intersect(t, s.a);
	if(intersect(line(s), t.a) && intersect(line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}
int intersect(const circle &c, const segment &s) {
	const point h = projection(s, c.center);
	const int c0 = compare(distance(h, c.center), c.radius);
	if(c0 == 1) return 0;
	if(c0 == 0) return intersect(s, h);
	const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius);
	if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0);
	return intersect(s, h) ? 2 : 0;
}
int intersect(const segment &s, const circle &c) { return intersect(c, s); }
int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

// distance of two shaps
R distance(const point &a, const point &b) { return fabs(a - b); }
R distance(const line &l, const point &p) { return distance(p, projection(l, p)); }
R distance(const point &p, const line &l) { return distance(l, p); }
R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; }
R distance(const segment &s, const point &p) {
	const point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p));
}
R distance(const point &p, const segment &s) { return distance(s, p); }
R distance(const segment &a, const segment &b) {
	if(intersect(a, b)) return R(0);
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}
R distance(const line &l, const segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}
R distance(const segment &s, const line &l) { return distance(l, s); }
R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); }
R distance(const point &p, const circle &c) { return distance(c, p); }
R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); }
R distance(const line &l, const circle &c) { return distance(c, l); }
R distance(const circle &c1, const circle &c2) {
	const R d = distance(c1.center, c2.center);
	if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius;
	if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d;
	return R(0);
}
R distance(const circle &c, const segment &s) {
	const point p = projection(s, c.center);
	const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b));
	if(dist_min > c.radius) return dist_min - c.radius;
	const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b));
	return dist_max < c.radius ? c.radius - dist_max : R(0);
}
R distance(const segment &s, const circle &c) { return distance(c, s); }

point crosspoint(const line &l, const line &m) {
	R A = cross(l.b - l.a, m.b - m.a);
	R B = cross(l.b - l.a, l.b - m.a);
	if(eq(A, 0.)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}
point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); }
point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); }
point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); }
#line 4 "SPJ-Library/graph/graph.hpp"
#include <deque>
#include <iostream>
#include <queue>
#include <tuple>
#line 9 "SPJ-Library/graph/graph.hpp"

#pragma region graph

template <class cost_type = long long>
class graph {
   public:
	struct edge {
	   public:
		int from, to;
		cost_type cost;
		int id;
		edge() = default;
		edge(int from_, int to_, cost_type cost_ = 1, int id_ = -1) : from(from_), to(to_), cost(cost_), id(id_) {}
		bool operator<(const edge &a) const { return cost < a.cost; }
		bool operator>(const edge &a) const { return cost > a.cost; }
		friend std::ostream &operator<<(std::ostream &s, const edge &a) {
			s << '(' << a.from << " -> " << a.to << "), cost: " << a.cost << ", id: " << a.id;
			return s;
		}
	};

   private:
	std::vector<std::vector<edge>> edges;
	int next_edge_id = 0;

   public:
	inline const std::vector<edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<edge> &operator[](int k) { return edges[k]; }

	int size() const { return int(edges.size()); }
	void resize(const int n) { edges.resize(n); }
	int edge_count() const { return next_edge_id; }

	friend std::ostream &operator<<(std::ostream &s, const graph<cost_type> &g) {
		for(const auto &adj : g.edges)
			for(const auto &ed : adj) s << ed << '\n';
		return s;
	}

	graph() = default;
	graph(int n) : edges(n) {}
	graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const cost_type INF = std::numeric_limits<cost_type>::max() / 3;

	void input(int e = -1, bool weight = false, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			std::cin >> u >> v;
			cost_type cost = 1;
			if(weight) std::cin >> cost;
			add_edge(u, v, cost, directed, idx);
		}
	}

	inline int add_edge(int u, int v, cost_type cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(u, v, cost, next_edge_id);
		if(!directed && u != v) edges[v].emplace_back(v, u, cost, next_edge_id);
		return next_edge_id++;
	}

	// Ο(V+E)
	
};
#pragma endregion
#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 7 "SPJ-Library/template/basic_func.hpp"

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 7 "a.cpp"

point rot(const point& p) { return rotate(p, 1); }

R solve(int pipe_number) {
	int valve_number;
	cin >> valve_number;
	segments pipes;
	points pts;
	vector<int> left(pipe_number), right(pipe_number);
	R ret = 0.;
	rep(i, pipe_number) {
		point s, t;
		cin >> s >> t;
		s = rot(s);
		t = rot(t);
		if(t < s) swap(s, t);
		ret += distance(s, t);
		pipes.emplace_back(s, t);
		left[i] = (int)pts.size();
		pts.push_back(s);
		right[i] = int(pts.size());
		pts.push_back(t);
	}
	vvi crs(pipe_number, vi(pipe_number, -1));
	vector<vi> on_points(pipe_number);
	rep(i, pipe_number) rep(j, i + 1, pipe_number) {
		const segment& segi = pipes[i];
		const segment& segj = pipes[j];
		if(intersect(segi, segj)) {
			crs[i][j] = crs[j][i] = int(pts.size());
			point crspt = crosspoint(segi, segj);
			pts.push_back(crspt);
			on_points[i].push_back(crs[i][j]);
			on_points[j].push_back(crs[i][j]);
		}
	}
	vector<int> valve_id(valve_number + 2);

	foa(setid, valve_id) {
		point valve;
		cin >> valve;
		valve = rot(valve);
		vector<int> crosses;
		rep(pipeid, pipe_number) {
			if(intersect(valve, pipes[pipeid])) {
				crosses.push_back(pipeid);
			}
		}
		assert(int(crosses.size()) <= 2 && crosses.size());
		if(crosses.size() == 1) {
			setid = (int)pts.size();
			pts.push_back(valve);
			foa(pipeid, crosses) { on_points[pipeid].push_back(setid); }
		} else {
			setid = crs[crosses.front()][crosses.back()];
		}
	}

	const int source = valve_id[valve_number];
	const int repair = valve_id[valve_number + 1];
	graph<R> g(int(pts.size()));

	rep(i, pipe_number) {
		vector<int>& ids = on_points[i];
		sort(all(ids), [&pts](int ii, int j) { return pts[ii] < pts[j]; });
		debug(i, ids);
		ids.push_back(right[i]);
		ids.insert(ids.begin(), left[i]);

		rep(j, int(ids.size()) - 1) {
			int from = ids[j];
			int to = ids[j + 1];
			g.add_edge(from, to, distance(pts[from], pts[to]), false, 0);
		}
	}

	vector<int> point_id_to_valve_id(int(pts.size()), -1);
	rep(i, valve_number) point_id_to_valve_id[valve_id[i]] = i;
	vector<int> closed(int(pts.size())), visited(int(pts.size()));

	queue<int> q;
	q.push(repair);
	visited[repair] = 1;
	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(nxt, g[now]) {
			debug(now, nxt.to);
			if(visited[nxt.to]) continue;
			const int vid = point_id_to_valve_id[nxt.to];
			if(vid != -1) closed[nxt.to] = 1;
			if(!closed[nxt.to]) {
				q.push(nxt.to);
				visited[nxt.to] = 1;
			}
		}
	}
	if(visited[source]) return -2;

	q.push(source);
	visited.assign(int(pts.size()), 0);
	visited[source] = 1;

	set<int> reduced_ids;

	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(e, g[now]) {
			if(!reduced_ids.count(e.id)) {
				ret -= e.cost;
				reduced_ids.insert(e.id);
			}
			if(!visited[e.to] && !closed[e.to]) {
				q.push(e.to);
				visited[e.to] = 1;
			}
		}
	}

	return ret;
}

int main() {
	int pipe_number;
	while(cin >> pipe_number && pipe_number) {
		R ans = solve(pipe_number);
		if(ans < -1)
			print(-1);
		else
			print(ans);
	}
}
accuracy: 0.2054794520547945
time_ms: 10
memory_kb: 8472
final_rank: 18

code_snippet: #line 1 "a.cpp"
/*	author:  Kite_kuma
	created: 2022.07.07 11:44:43 */

#line 2 "SPJ-Library/geometry/geometry.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>

using R = long double;
using point = std::complex<R>;
using arrow = point;
const R EPS(1e-10), PI(acosl(-1));

inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; }
inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; }
/*
	sign of x
	-1: x < 0
	 0: x == 0
	 1: x > 0
*/
inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
/*
	sign of (a-b)
	-1: a < b
	 0: a == b
	 1: a > b
*/
inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

std::istream &operator>>(std::istream &is, point &p) {
	R a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; }

// rotate point 'p' for counter clockwise direction
point rotate(const point &p, const R &theta) {
	return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag());
}

R radian_to_degree(const R &r) { return (r * 180.0 / PI); }
R degree_to_radian(const R &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
R get_angle(const point &a, const point &b, const point &c) {
	const point v(a - b), w(c - b);
	R theta = fabsl(atan2l(w.imag(), w.real()) - atan2l(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const point &a, const point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct segment;
struct line {
	point a, b;
	line() = default;
	line(const point &a, const point &b) : a(a), b(b) {}
	// Ax + By + C = 0
	line(const R &A, const R &B, const R &C) {
		if(eq(A, 0)) {
			assert(!eq(B, 0));
			a = point(0, -C / B), b = point(1, -(A + C) / B);
		} else {
			a = point(-C / A, 0), b = point(-(B + C) / A, 1);
		}
	}
	explicit line(const segment &seg);
	friend std::ostream &operator<<(std::ostream &os, line &ln) { return os << '(' << ln.a << " -- " << ln.b << ')'; }
	friend std::istream &operator>>(std::istream &is, line &a) { return is >> a.a >> a.b; }
};
struct segment {
	point a, b;
	segment() = default;
	segment(const point &a, const point &b) : a(a), b(b) {}
	explicit segment(const line &ln) : a(ln.a), b(ln.b) {}
	friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; }
	friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; }
};
line::line(const segment &seg) : a(seg.a), b(seg.b) {}

struct circle {
	point center;
	R radius;
	circle() = default;
	circle(const point &center, const R &radius) : center(center), radius(radius) {}
};

using points = std::vector<point>;
using polygon = std::vector<point>;
using segments = std::vector<segment>;
using lines = std::vector<line>;
using circles = std::vector<circle>;

R cross(const point &a, const point &b) { return real(a) * imag(b) - imag(a) * real(b); }
R dot(const point &a, const point &b) { return real(a) * real(b) + imag(a) * imag(b); }

enum CCW {
	ONLINE_FRONT = -2,
	CLOCKWISE = -1,
	ON_SEGMENT = 0,
	COUNTER_CLOCKWISE = 1,
	ONLINE_BACK = 2,
};
int ccw(const point &a, point b, point c) {
	b -= a, c -= a;
	const R crs_b_c = cross(b, c);
	if(crs_b_c > EPS) return CCW::COUNTER_CLOCKWISE;
	if(crs_b_c < -EPS) return CCW::CLOCKWISE;
	if(dot(b, c) < -EPS) return CCW::ONLINE_BACK;
	if(norm(b) + EPS < norm(c)) return CCW::ONLINE_FRONT;
	return CCW::ON_SEGMENT;
}

bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); }
bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }

bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); }
bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }

point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); }
point projection(const segment &s, const point &p) { return projection(line(s), p); }

point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; }
point reflection(const segment &s, const point &p) { return projection(line(s), p); }

R distance(const point &p, const point &q);
R distance(const line &l, const point &p);
int number_of_common_tangents(const circle &c1, const circle &c2) {
	const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
}

// number of common points (-1: infinite)
int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }
int intersect(const point &p, const line &l) { return intersect(l, p); }
int intersect(const line &l, const line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(!parallel(l, m));
}
int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); }
int intersect(const point &p, const segment &s) { return intersect(s, p); }
int intersect(const line &l, const segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1;
}
int intersect(const segment &s, const line &l) { return intersect(l, s); }
int intersect(const circle &c, const line &l) {
	R d = c.radius - distance(l, c.center);
	return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0;
}
int intersect(const line &l, const circle &c) { return intersect(c, l); }
int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); }
int intersect(const point &p, const circle &c) { return intersect(c, p); }
int intersect(const segment &s, const segment &t) {
	if(same_point(s.a, s.b)) return intersect(t, s.a);
	if(intersect(line(s), t.a) && intersect(line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}
int intersect(const circle &c, const segment &s) {
	const point h = projection(s, c.center);
	const int c0 = compare(distance(h, c.center), c.radius);
	if(c0 == 1) return 0;
	if(c0 == 0) return intersect(s, h);
	const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius);
	if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0);
	return intersect(s, h) ? 2 : 0;
}
int intersect(const segment &s, const circle &c) { return intersect(c, s); }
int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

// distance of two shaps
R distance(const point &a, const point &b) { return fabs(a - b); }
R distance(const line &l, const point &p) { return distance(p, projection(l, p)); }
R distance(const point &p, const line &l) { return distance(l, p); }
R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; }
R distance(const segment &s, const point &p) {
	const point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p));
}
R distance(const point &p, const segment &s) { return distance(s, p); }
R distance(const segment &a, const segment &b) {
	if(intersect(a, b)) return R(0);
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}
R distance(const line &l, const segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}
R distance(const segment &s, const line &l) { return distance(l, s); }
R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); }
R distance(const point &p, const circle &c) { return distance(c, p); }
R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); }
R distance(const line &l, const circle &c) { return distance(c, l); }
R distance(const circle &c1, const circle &c2) {
	const R d = distance(c1.center, c2.center);
	if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius;
	if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d;
	return R(0);
}
R distance(const circle &c, const segment &s) {
	const point p = projection(s, c.center);
	const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b));
	if(dist_min > c.radius) return dist_min - c.radius;
	const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b));
	return dist_max < c.radius ? c.radius - dist_max : R(0);
}
R distance(const segment &s, const circle &c) { return distance(c, s); }

point crosspoint(const line &l, const line &m) {
	R A = cross(l.b - l.a, m.b - m.a);
	R B = cross(l.b - l.a, l.b - m.a);
	if(eq(A, 0.)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}
point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); }
point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); }
point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); }



#line 4 "SPJ-Library/graph/graph.hpp"
#include <deque>
#include <iostream>
#include <queue>
#include <tuple>
#line 9 "SPJ-Library/graph/graph.hpp"

#pragma region graph

template <class cost_type = long long>
class graph {
   public:
	struct edge {
	   public:
		int from, to;
		cost_type cost;
		int id;
		edge() = default;
		edge(int from_, int to_, cost_type cost_ = 1, int id_ = -1) : from(from_), to(to_), cost(cost_), id(id_) {}
		bool operator<(const edge &a) const { return cost < a.cost; }
		bool operator>(const edge &a) const { return cost > a.cost; }
		friend std::ostream &operator<<(std::ostream &s, const edge &a) {
			s << '(' << a.from << " -> " << a.to << "), cost: " << a.cost << ", id: " << a.id;
			return s;
		}
	};

   private:
	std::vector<std::vector<edge>> edges;
	int next_edge_id = 0;

   public:
	inline const std::vector<edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<edge> &operator[](int k) { return edges[k]; }

	int size() const { return int(edges.size()); }
	void resize(const int n) { edges.resize(n); }
	int edge_count() const { return next_edge_id; }

	friend std::ostream &operator<<(std::ostream &s, const graph<cost_type> &g) {
		for(const auto &adj : g.edges)
			for(const auto &ed : adj) s << ed << '\n';
		return s;
	}

	graph() = default;
	graph(int n) : edges(n) {}
	graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const cost_type INF = std::numeric_limits<cost_type>::max() / 3;

	void input(int e = -1, bool weight = false, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			std::cin >> u >> v;
			cost_type cost = 1;
			if(weight) std::cin >> cost;
			add_edge(u, v, cost, directed, idx);
		}
	}

	inline int add_edge(int u, int v, cost_type cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(u, v, cost, next_edge_id);
		if(!directed && u != v) edges[v].emplace_back(v, u, cost, next_edge_id);
		return next_edge_id++;
	}

};
#pragma endregion
#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 7 "SPJ-Library/template/basic_func.hpp"

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 7 "a.cpp"

point rot(const point& p) { return rotate(p, 1); }

R solve(int pipe_number) {
	int valve_number;
	cin >> valve_number;
	segments pipes;
	points pts;
	vector<int> left(pipe_number), right(pipe_number);
	R ret = 0.;
	rep(i, pipe_number) {
		point s, t;
		cin >> s >> t;
		s = rot(s);
		t = rot(t);
		if(t < s) swap(s, t);
		ret += distance(s, t);
		pipes.emplace_back(s, t);
		left[i] = (int)pts.size();
		pts.push_back(s);
		right[i] = int(pts.size());
		pts.push_back(t);
	}
	vvi crs(pipe_number, vi(pipe_number, -1));
	rep(i, pipe_number) rep(j, i + 1, pipe_number) {
		const segment& segi = pipes[i];
		const segment& segj = pipes[j];
		if(intersect(segi, segj)) {
			crs[i][j] = crs[j][i] = int(pts.size());
			point crspt = crosspoint(segi, segj);
			pts.push_back(crspt);
		}
	}
	vector<int> valve_id(valve_number + 2);

	vector<vi> on_points(pipe_number);

	foa(setid, valve_id) {
		point valve;
		cin >> valve;
		valve = rot(valve);
		vector<int> crosses;
		rep(pipeid, pipe_number) {
			if(intersect(valve, pipes[pipeid])) {
				crosses.push_back(pipeid);
			}
		}
		assert(int(crosses.size()) <= 2 && crosses.size());
		if(crosses.size() == 1) {
			setid = (int)pts.size();
			pts.push_back(valve);
			foa(pipeid, crosses) { on_points[pipeid].push_back(setid); }
		} else {
			setid = crs[crosses.front()][crosses.back()];
		}
	}

	const int source = valve_id[valve_number];
	const int repair = valve_id[valve_number + 1];
	graph<R> g(int(pts.size()));

	rep(i, pipe_number) {
		vector<int>& ids = on_points[i];
		rep(j, pipe_number) {
			const int c = crs[i][j];
			if(c != -1) ids.push_back(c);
		}
		sort(all(ids), [&pts](int ii, int j) { return pts[ii] < pts[j]; });
		debug(i, ids);
		ids.push_back(right[i]);
		ids.insert(ids.begin(), left[i]);

		rep(j, int(ids.size()) - 1) {
			int from = ids[j];
			int to = ids[j + 1];
			g.add_edge(from, to, distance(pts[from], pts[to]), false, 0);
		}
	}

	vector<int> point_id_to_valve_id(int(pts.size()), -1);
	rep(i, valve_number) point_id_to_valve_id[valve_id[i]] = i;
	vector<int> closed(int(pts.size())), visited(int(pts.size()));

	queue<int> q;
	q.push(repair);
	visited[repair] = 1;
	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(nxt, g[now]) {
			debug(now, nxt.to);
			if(visited[nxt.to]) continue;
			const int vid = point_id_to_valve_id[nxt.to];
			if(vid != -1) closed[nxt.to] = 1;
			if(!closed[nxt.to]) {
				q.push(nxt.to);
				visited[nxt.to] = 1;
			}
		}
	}
	if(visited[source]) return -1;

	debug(source, repair);
	debug(pts);
	debug(visited);
	debug(closed);

	q.push(source);
	visited.assign(int(pts.size()), 0);
	visited[source] = 1;

	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(e, g[now]) {
			R minus = closed[e.to] ? e.cost : e.cost / 2;
			ret -= minus;
			if(e.cost > EPS) debug(now, e.to, e.cost, minus);
			if(!visited[e.to] && !closed[e.to]) {
				q.push(e.to);
				visited[e.to] = 1;
			}
		}
	}

	return ret;
}

int main() {
	int pipe_number;
	while(cin >> pipe_number && pipe_number) {
		R ans = solve(pipe_number);
		if(ans < 0)
			print(-1);
		else
			print(ans);
	}
}
accuracy: 0.2054794520547945
time_ms: 10
memory_kb: 7624
final_rank: 17

code_snippet: #line 1 "a.cpp"
/*	author:  Kite_kuma
	created: 2022.07.07 11:44:43 */

#line 2 "SPJ-Library/geometry/geometry.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>

using R = long double;
using point = std::complex<R>;
using arrow = point;
const R EPS(1e-10), PI(acosl(-1));

inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; }
inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; }
/*
	sign of x
	-1: x < 0
	 0: x == 0
	 1: x > 0
*/
inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
/*
	sign of (a-b)
	-1: a < b
	 0: a == b
	 1: a > b
*/
inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

std::istream &operator>>(std::istream &is, point &p) {
	R a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; }

// rotate point 'p' for counter clockwise direction
point rotate(const point &p, const R &theta) {
	return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag());
}

R radian_to_degree(const R &r) { return (r * 180.0 / PI); }
R degree_to_radian(const R &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
R get_angle(const point &a, const point &b, const point &c) {
	const point v(a - b), w(c - b);
	R theta = fabsl(atan2l(w.imag(), w.real()) - atan2l(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const point &a, const point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct segment;
struct line {
	point a, b;
	line() = default;
	line(const point &a, const point &b) : a(a), b(b) {}
	// Ax + By + C = 0
	line(const R &A, const R &B, const R &C) {
		if(eq(A, 0)) {
			assert(!eq(B, 0));
			a = point(0, -C / B), b = point(1, -(A + C) / B);
		} else {
			a = point(-C / A, 0), b = point(-(B + C) / A, 1);
		}
	}
	explicit line(const segment &seg);
	friend std::ostream &operator<<(std::ostream &os, line &ln) { return os << '(' << ln.a << " -- " << ln.b << ')'; }
	friend std::istream &operator>>(std::istream &is, line &a) { return is >> a.a >> a.b; }
};
struct segment {
	point a, b;
	segment() = default;
	segment(const point &a, const point &b) : a(a), b(b) {}
	explicit segment(const line &ln) : a(ln.a), b(ln.b) {}
	friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; }
	friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; }
};
line::line(const segment &seg) : a(seg.a), b(seg.b) {}

struct circle {
	point center;
	R radius;
	circle() = default;
	circle(const point &center, const R &radius) : center(center), radius(radius) {}
};

using points = std::vector<point>;
using polygon = std::vector<point>;
using segments = std::vector<segment>;
using lines = std::vector<line>;
using circles = std::vector<circle>;

R cross(const point &a, const point &b) { return real(a) * imag(b) - imag(a) * real(b); }
R dot(const point &a, const point &b) { return real(a) * real(b) + imag(a) * imag(b); }

enum CCW {
	ONLINE_FRONT = -2,
	CLOCKWISE = -1,
	ON_SEGMENT = 0,
	COUNTER_CLOCKWISE = 1,
	ONLINE_BACK = 2,
};
int ccw(const point &a, point b, point c) {
	b -= a, c -= a;
	const R crs_b_c = cross(b, c);
	if(crs_b_c > EPS) return CCW::COUNTER_CLOCKWISE;
	if(crs_b_c < -EPS) return CCW::CLOCKWISE;
	if(dot(b, c) < -EPS) return CCW::ONLINE_BACK;
	if(norm(b) + EPS < norm(c)) return CCW::ONLINE_FRONT;
	return CCW::ON_SEGMENT;
}

bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); }
bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }

bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); }
bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }

point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); }
point projection(const segment &s, const point &p) { return projection(line(s), p); }

point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; }
point reflection(const segment &s, const point &p) { return projection(line(s), p); }

R distance(const point &p, const point &q);
R distance(const line &l, const point &p);
int number_of_common_tangents(const circle &c1, const circle &c2) {
	const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
}

// number of common points (-1: infinite)
int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }
int intersect(const point &p, const line &l) { return intersect(l, p); }
int intersect(const line &l, const line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(!parallel(l, m));
}
int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); }
int intersect(const point &p, const segment &s) { return intersect(s, p); }
int intersect(const line &l, const segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1;
}
int intersect(const segment &s, const line &l) { return intersect(l, s); }
int intersect(const circle &c, const line &l) {
	R d = c.radius - distance(l, c.center);
	return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0;
}
int intersect(const line &l, const circle &c) { return intersect(c, l); }
int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); }
int intersect(const point &p, const circle &c) { return intersect(c, p); }
int intersect(const segment &s, const segment &t) {
	if(same_point(s.a, s.b)) return intersect(t, s.a);
	if(intersect(line(s), t.a) && intersect(line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}
int intersect(const circle &c, const segment &s) {
	const point h = projection(s, c.center);
	const int c0 = compare(distance(h, c.center), c.radius);
	if(c0 == 1) return 0;
	if(c0 == 0) return intersect(s, h);
	const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius);
	if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0);
	return intersect(s, h) ? 2 : 0;
}
int intersect(const segment &s, const circle &c) { return intersect(c, s); }
int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

// distance of two shaps
R distance(const point &a, const point &b) { return fabs(a - b); }
R distance(const line &l, const point &p) { return distance(p, projection(l, p)); }
R distance(const point &p, const line &l) { return distance(l, p); }
R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; }
R distance(const segment &s, const point &p) {
	const point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p));
}
R distance(const point &p, const segment &s) { return distance(s, p); }
R distance(const segment &a, const segment &b) {
	if(intersect(a, b)) return R(0);
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}
R distance(const line &l, const segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}
R distance(const segment &s, const line &l) { return distance(l, s); }
R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); }
R distance(const point &p, const circle &c) { return distance(c, p); }
R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); }
R distance(const line &l, const circle &c) { return distance(c, l); }
R distance(const circle &c1, const circle &c2) {
	const R d = distance(c1.center, c2.center);
	if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius;
	if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d;
	return R(0);
}
R distance(const circle &c, const segment &s) {
	const point p = projection(s, c.center);
	const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b));
	if(dist_min > c.radius) return dist_min - c.radius;
	const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b));
	return dist_max < c.radius ? c.radius - dist_max : R(0);
}
R distance(const segment &s, const circle &c) { return distance(c, s); }

point crosspoint(const line &l, const line &m) {
	R A = cross(l.b - l.a, m.b - m.a);
	R B = cross(l.b - l.a, l.b - m.a);
	if(eq(A, 0.)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}
point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); }
point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); }
point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); }



#line 4 "SPJ-Library/graph/graph.hpp"
#include <deque>
#include <iostream>
#include <queue>
#include <tuple>
#line 9 "SPJ-Library/graph/graph.hpp"

#pragma region graph

template <class cost_type = long long>
class graph {
   public:
	struct edge {
	   public:
		int from, to;
		cost_type cost;
		int id;
		edge() = default;
		edge(int from_, int to_, cost_type cost_ = 1, int id_ = -1) : from(from_), to(to_), cost(cost_), id(id_) {}
		bool operator<(const edge &a) const { return cost < a.cost; }
		bool operator>(const edge &a) const { return cost > a.cost; }
		friend std::ostream &operator<<(std::ostream &s, const edge &a) {
			s << '(' << a.from << " -> " << a.to << "), cost: " << a.cost << ", id: " << a.id;
			return s;
		}
	};

   private:
	std::vector<std::vector<edge>> edges;
	int next_edge_id = 0;

   public:
	inline const std::vector<edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<edge> &operator[](int k) { return edges[k]; }

	int size() const { return int(edges.size()); }
	void resize(const int n) { edges.resize(n); }
	int edge_count() const { return next_edge_id; }

	friend std::ostream &operator<<(std::ostream &s, const graph<cost_type> &g) {
		for(const auto &adj : g.edges)
			for(const auto &ed : adj) s << ed << '\n';
		return s;
	}

	graph() = default;
	graph(int n) : edges(n) {}
	graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const cost_type INF = std::numeric_limits<cost_type>::max() / 3;

	void input(int e = -1, bool weight = false, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			std::cin >> u >> v;
			cost_type cost = 1;
			if(weight) std::cin >> cost;
			add_edge(u, v, cost, directed, idx);
		}
	}

	inline int add_edge(int u, int v, cost_type cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(u, v, cost, next_edge_id);
		if(!directed && u != v) edges[v].emplace_back(v, u, cost, next_edge_id);
		return next_edge_id++;
	}

};
#pragma endregion
#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 7 "SPJ-Library/template/basic_func.hpp"

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 7 "a.cpp"

point rot(const point& p) { return rotate(p, 0.001); }

R solve(int pipe_number) {
	int valve_number;
	cin >> valve_number;
	segments pipes;
	points pts;
	vector<int> left(pipe_number), right(pipe_number);
	R ret = 0.;
	rep(i, pipe_number) {
		point s, t;
		cin >> s >> t;
		s = rot(s);
		t = rot(t);
		if(t < s) swap(s, t);
		ret += distance(s, t);
		pipes.emplace_back(s, t);
		left[i] = (int)pts.size();
		pts.push_back(s);
		right[i] = int(pts.size());
		pts.push_back(t);
	}
	vvi crs(pipe_number, vi(pipe_number, -1));
	rep(i, pipe_number) rep(j, i + 1, pipe_number) {
		const segment& segi = pipes[i];
		const segment& segj = pipes[j];
		if(intersect(segi, segj)) {
			crs[i][j] = crs[j][i] = int(pts.size());
			point crspt = crosspoint(segi, segj);
			pts.push_back(crspt);
		}
	}
	vector<int> valve_id(valve_number + 2);

	vector<vi> on_points(pipe_number);

	foa(setid, valve_id) {
		point valve;
		cin >> valve;
		valve = rot(valve);
		vector<int> crosses;
		rep(pipeid, pipe_number) {
			if(intersect(valve, pipes[pipeid])) {
				crosses.push_back(pipeid);
			}
		}
		assert(int(crosses.size()) <= 2 && crosses.size());
		if(crosses.size() == 1) {
			setid = (int)pts.size();
			pts.push_back(valve);
			foa(pipeid, crosses) { on_points[pipeid].push_back(setid); }
		} else {
			setid = crs[crosses.front()][crosses.back()];
		}
	}

	const int source = valve_id[valve_number];
	const int repair = valve_id[valve_number + 1];
	graph<R> g(int(pts.size()));

	rep(i, pipe_number) {
		vector<int>& ids = on_points[i];
		rep(j, pipe_number) {
			const int c = crs[i][j];
			if(c != -1) ids.push_back(c);
		}
		sort(all(ids), [&pts](int ii, int j) { return pts[ii] < pts[j]; });
		debug(i, ids);
		ids.push_back(right[i]);
		ids.insert(ids.begin(), left[i]);

		rep(j, int(ids.size()) - 1) {
			int from = ids[j];
			int to = ids[j + 1];
			g.add_edge(from, to, distance(pts[from], pts[to]), false, 0);
		}
	}

	vector<int> point_id_to_valve_id(int(pts.size()), -1);
	rep(i, valve_number) point_id_to_valve_id[valve_id[i]] = i;
	vector<int> closed(int(pts.size())), visited(int(pts.size()));

	queue<int> q;
	q.push(repair);
	visited[repair] = 1;
	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(nxt, g[now]) {
			debug(now, nxt.to);
			if(visited[nxt.to]) continue;
			const int vid = point_id_to_valve_id[nxt.to];
			if(vid != -1) closed[nxt.to] = 1;
			if(!closed[nxt.to]) {
				q.push(nxt.to);
				visited[nxt.to] = 1;
			}
		}
	}
	if(visited[source]) return -1;

	debug(source, repair);
	debug(pts);
	debug(visited);
	debug(closed);

	q.push(source);
	visited.assign(int(pts.size()), 0);
	visited[source] = 1;

	while(q.size()) {
		int now = q.front();
		q.pop();
		foa(e, g[now]) {
			R minus = closed[e.to] ? e.cost : e.cost / 2;
			ret -= minus;
			if(e.cost > EPS) debug(now, e.to, e.cost, minus);
			if(!visited[e.to] && !closed[e.to]) {
				q.push(e.to);
				visited[e.to] = 1;
			}
		}
	}

	return ret;
}

int main() {
	int pipe_number;
	while(cin >> pipe_number && pipe_number) {
		R ans = solve(pipe_number);
		if(ans < 0)
			print(-1);
		else
			print(ans);
	}
}
accuracy: 0.2054794520547945
time_ms: 10
memory_kb: 7376
final_rank: 16

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 1;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

typedef complex<ld> Point;
ld dot(Point a, Point b) { return real(conj(a) * b); }
ld cross(Point a, Point b) { return imag(conj(a) * b); }
namespace std {
	bool operator<(const Point& lhs, const Point& rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
struct Line {
	Point a, b;
};
struct Circle {
	Point p; ld r;
};
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//counter clockwise
	if (cross(b, c) < -eps)return -1;//clock wise
	if (dot(b, c) < 0)return 2;//c--a--b on line
	if (norm(b) < norm(c))return -2;//a--b--c on line
	return 0; //a--c--b on line
}
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
//線分と線分の交差判定2
bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
//直線と直線の交点
//平行な２直線に対しては使うな！！！！
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

Point input_point() {
	int x, y; cin >> x >> y;
	return { (ld)x,(ld)y };
}
void solve() {
	int n, m; cin >> n >> m;
	vector<Line> s(n);
	rep(i, n) {
		s[i] = { input_point(),input_point() };
	}
	vector<Point> p(m);
	rep(i, m) {
		p[i] = input_point();
	}
	Point sta, goa;
	sta = input_point(); goa = input_point();
	vector<Point> vs;
	vector<int> ste;
	auto isin = [&](Point p)->bool {
		rep(i, vs.size()) {
			ld dif = abs(p - vs[i]);
			if (dif < eps)return true;
		}
		return false;
	};
	vs.push_back(sta);
	ste.push_back(2);
	vs.push_back(goa);
	ste.push_back(3);
	rep(i, m) {
		vs.push_back(p[i]);
		ste.push_back(1);
	}
	rep(i, n) {
		if (!isin(s[i].a)) {
			vs.push_back(s[i].a);
			ste.push_back(0);
		}
		if (!isin(s[i].b)) {
			vs.push_back(s[i].b);
			ste.push_back(0);
		}
	}
	rep(i, n)Rep(j, i + 1, n)if (isis_ss(s[i], s[j])) {
		Point cc = is_ll(s[i], s[j]);
		if (!isin(cc)) {
			vs.push_back(cc);
			ste.push_back(0);
		}
	}
	int sz = vs.size();
	vector<vector<int>> G(sz);
	rep(i, n) {
		vector<pair<ld, int>> vp;
		rep(j, vs.size()) {
			if (isis_sp(s[i], vs[j])) {
				ld dist = abs(s[i].a - vs[j]);
				vp.push_back({ dist,j });
			}
		}
		sort(all(vp));
		rep(j, (int)vp.size() - 1) {
			int le = vp[j].second;
			int ri = vp[j + 1].second;
			G[le].push_back(ri);
			G[ri].push_back(le);
		}
	}
	vector<bool> used(sz);
	used[1] = true;
	queue<int> q; q.push(1);
	while (!q.empty()) {
		int id = q.front(); q.pop();
		if (ste[id] == 1)continue;
		for (int to : G[id]) {
			if (!used[to]) {
				used[to] = true; q.push(to);
			}
		}
	}
	if (used[0]) {
		cout << -1 << "\n"; return;
	}
	vector<bool> cused(sz);
	cused[0] = true;
	q.push(0);
	while (!q.empty()) {
		int id = q.front(); q.pop();
		if (used[id])continue;
		for (int to : G[id]) {
			if (!cused[to]) {
				cused[to] = true; q.push(to);
			}
		}
	}
	ld ans = 0;
	rep(i, sz)for (int to : G[i])if (i < to) {
		ld cost = abs(vs[i] - vs[to]);
		if (!cused[i]) {
			ans += cost;
		}
		else {
			if (used[i] && used[to]) {
				ans += cost;
			}
		}
	}
	cout << ans << "\n";
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t;rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 1130
memory_kb: 4324
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


//#define EPS 0.0000001
#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return fabs(x-p.x) > EPS? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index = -1,repair_index = -1;
vector<Info> on_segment[NUM];
vector<Point> NODES,STOP_VALVE;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<int,bool> IS_STOP;
map<pair<int,int>,bool> MAP;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}


double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//★★点と線分の距離★★
double getDistanceSP(Line l,Point p){
	if(dot(l.p[1]-l.p[0],p-l.p[0]) < 0.0) return abs(p-l.p[0]);
	if(dot(l.p[0]-l.p[1],p-l.p[1]) < 0.0) return abs(p-l.p[1]);
	return getDistanceLP(l,p);
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	int x1,y1,x2,y2;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&x1,&y1,&x2,&y2);

		water_pipe[i].p[0].x = x1;
		water_pipe[i].p[0].y = y1;
		water_pipe[i].p[1].x = x2;
		water_pipe[i].p[1].y = y2;

		auto at = MAP.find(make_pair(x1,y1));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[0]));
			MAP[make_pair(x1,y1)] = true;
		}

		at = MAP.find(make_pair(x2,y2));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[1]));
			MAP[make_pair(x2,y2)] = true;
		}

		NODES.push_back(Point(water_pipe[i].p[1]));
	}


	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);

		STOP_VALVE.push_back(Point(x,y));

		NODES.push_back(Point(x,y));

	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);
	NODES.push_back(Point(start_x,start_y));


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);
	NODES.push_back(Point(repair_x,repair_y));

	//パイプとパイプの交点ノードの座標を求める

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			if(water_pipe[i].p[0] == water_pipe[k].p[0] || water_pipe[i].p[0] == water_pipe[k].p[1] || //計算不要なのでSKIP
					water_pipe[i].p[1] == water_pipe[k].p[0] || water_pipe[i].p[1] == water_pipe[k].p[1])continue;

			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);

			bool FLG = false;
			for(int a = 0; a < NODES.size(); a++){

				if(NODES[a] == tmp_point){
					FLG = true;
					break;
				}
			}

			if(FLG)continue;

			NODES.push_back(tmp_point);

		}
	}

	sort(NODES.begin(),NODES.end());
	NODES.erase(unique(NODES.begin(),NODES.end()),NODES.end());

	//線分と接触しているノードを線分に所属させる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == water_pipe[i].p[0] || NODES[k] == water_pipe[i].p[1]){ //計算するとnanになる
				on_segment[i].push_back(Info(NODES[k],k));
				continue;
			}

			if(getDistanceSP(water_pipe[i],NODES[k]) > EPS)continue;

			on_segment[i].push_back(Info(NODES[k],k));
		}
	}

	//止水バルブのインデックスを求める
	for(int i = 0; i < STOP_VALVE.size(); i++){

		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == STOP_VALVE[i]){
				IS_STOP[k] = true;
				break;
			}

		}
	}


	//スタートノードのインデックスを求める
	Point start_point = Point(start_x,start_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == start_point){
			start_index = k;
			break;
		}
	}

	//修理ポイントのインデックスを求める
	Point repair_point = Point(repair_x,repair_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == repair_point){
			repair_index = k;
			break;
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = IS_STOP.find(tmp_node);

		if(at != IS_STOP.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}
	printf("%.10lf\n",total_length-can_supply);

	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 10288
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index = -1,repair_index = -1;
vector<Info> on_segment[NUM];
vector<Point> NODES,STOP_VALVE;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<int,bool> IS_STOP;
map<pair<int,int>,bool> MAP;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}


double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//★★点と線分の距離★★
double getDistanceSP(Line l,Point p){
	if(dot(l.p[1]-l.p[0],p-l.p[0]) < 0.0) return abs(p-l.p[0]);
	if(dot(l.p[0]-l.p[1],p-l.p[1]) < 0.0) return abs(p-l.p[1]);
	return getDistanceLP(l,p);
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	int x1,y1,x2,y2;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&x1,&y1,&x2,&y2);

		water_pipe[i].p[0].x = x1;
		water_pipe[i].p[0].y = y1;
		water_pipe[i].p[1].x = x2;
		water_pipe[i].p[1].y = y2;

		auto at = MAP.find(make_pair(x1,y1));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[0]));
			MAP[make_pair(x1,y1)] = true;
		}

		at = MAP.find(make_pair(x2,y2));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[1]));
			MAP[make_pair(x2,y2)] = true;
		}

		NODES.push_back(Point(water_pipe[i].p[1]));
	}

	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);
		NODES.push_back(Point(x,y));
		STOP_VALVE.push_back(Point(x,y));
	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);
	NODES.push_back(Point(start_x,start_y));


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);
	NODES.push_back(Point(repair_x,repair_y));

	//パイプとパイプの交点ノードの座標を求める

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			if(water_pipe[i].p[0] == water_pipe[k].p[0] || water_pipe[i].p[0] == water_pipe[k].p[1] || //計算不要なのでSKIP
					water_pipe[i].p[1] == water_pipe[k].p[0] || water_pipe[i].p[1] == water_pipe[k].p[1])continue;


			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			NODES.push_back(tmp_point);

		}
	}

	sort(NODES.begin(),NODES.end());
	NODES.erase(unique(NODES.begin(),NODES.end()));

	vector<Point> WORK;

	WORK = NODES;
	NODES.clear();

	Point pre = Point(-BIG_NUM,-BIG_NUM);

	for(int i = 0; i < WORK.size(); i++){
		if(fabs(WORK[i].x-pre.x) < EPS && fabs(WORK[i].y-pre.y) < EPS){

			//Do notghin

		}else{

			NODES.push_back(WORK[i]);
		}
		pre = WORK[i];
	}

	//線分と接触しているノードを線分に所属させる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == water_pipe[i].p[0] || NODES[k] == water_pipe[i].p[1]){ //計算するとnanになる
				on_segment[i].push_back(Info(NODES[k],k));
				continue;
			}

			if(getDistanceSP(water_pipe[i],NODES[k]) > EPS)continue;

			on_segment[i].push_back(Info(NODES[k],k));
		}
	}

	//止水バルブのインデックスを求める
	for(int i = 0; i < STOP_VALVE.size(); i++){

		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == STOP_VALVE[i]){
				IS_STOP[k] = true;
				//printf("%dは止水バルブ\n",k);
				break;
			}

		}
	}

	//スタートノードのインデックスを求める
	Point start_point = Point(start_x,start_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == start_point){
			start_index = k;
			break;
		}
	}
	//修理ポイントのインデックスを求める
	Point repair_point = Point(repair_x,repair_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == repair_point){
			repair_index = k;
			break;
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		vector<Info> work_segment;

		Point pre = Point(-BIG_NUM,-BIG_NUM);

		for(int k = 0; k < on_segment[i].size(); k++){
			if(fabs(on_segment[i][k].cross_point.x-pre.x) < EPS && fabs(on_segment[i][k].cross_point.y-pre.y) < EPS){

				//Do notghin

			}else{

				work_segment.push_back(on_segment[i][k]);
			}
			pre = on_segment[i][k].cross_point;
		}

		for(int k = 1; k < work_segment.size(); k++){

			int from = work_segment[k-1].index;
			int to = work_segment[k].index;

			double tmp_dist = calc_dist(work_segment[k-1].cross_point,work_segment[k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = IS_STOP.find(tmp_node);

		if(at != IS_STOP.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",total_length-can_supply);

	return 0;
}
accuracy: 0.273972602739726
time_ms: 50
memory_kb: 10336
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index = -1,repair_index = -1;
vector<Info> on_segment[NUM];
vector<Point> NODES,STOP_VALVE;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<int,bool> IS_STOP;
map<pair<int,int>,bool> MAP;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}


double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//★★点と線分の距離★★
double getDistanceSP(Line l,Point p){
	if(dot(l.p[1]-l.p[0],p-l.p[0]) < 0.0) return abs(p-l.p[0]);
	if(dot(l.p[0]-l.p[1],p-l.p[1]) < 0.0) return abs(p-l.p[1]);
	return getDistanceLP(l,p);
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	int x1,y1,x2,y2;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&x1,&y1,&x2,&y2);

		water_pipe[i].p[0].x = x1;
		water_pipe[i].p[0].y = y1;
		water_pipe[i].p[1].x = x2;
		water_pipe[i].p[1].y = y2;

		auto at = MAP.find(make_pair(x1,y1));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[0]));
			MAP[make_pair(x1,y1)] = true;
		}

		at = MAP.find(make_pair(x2,y2));
		if(at == MAP.end()){
			NODES.push_back(Point(water_pipe[i].p[1]));
			MAP[make_pair(x2,y2)] = true;
		}

		NODES.push_back(Point(water_pipe[i].p[1]));
	}

	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);
		NODES.push_back(Point(x,y));
		STOP_VALVE.push_back(Point(x,y));
	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);
	NODES.push_back(Point(start_x,start_y));


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);
	NODES.push_back(Point(repair_x,repair_y));

	//パイプとパイプの交点ノードの座標を求める

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			if(water_pipe[i].p[0] == water_pipe[k].p[0] || water_pipe[i].p[0] == water_pipe[k].p[1] || //計算不要なのでSKIP
					water_pipe[i].p[1] == water_pipe[k].p[0] || water_pipe[i].p[1] == water_pipe[k].p[1])continue;


			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			NODES.push_back(tmp_point);

		}
	}

	sort(NODES.begin(),NODES.end());
	NODES.erase(unique(NODES.begin(),NODES.end()));

	//線分と接触しているノードを線分に所属させる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == water_pipe[i].p[0] || NODES[k] == water_pipe[i].p[1]){ //計算するとnanになる
				on_segment[i].push_back(Info(NODES[k],k));
				continue;
			}

			if(getDistanceSP(water_pipe[i],NODES[k]) > EPS)continue;

			on_segment[i].push_back(Info(NODES[k],k));
		}
	}

	//止水バルブのインデックスを求める
	for(int i = 0; i < STOP_VALVE.size(); i++){

		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == STOP_VALVE[i]){
				IS_STOP[k] = true;
				break;
			}

		}
	}

	//スタートノードのインデックスを求める
	Point start_point = Point(start_x,start_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == start_point){
			start_index = k;
			break;
		}
	}

	//修理ポイントのインデックスを求める
	Point repair_point = Point(repair_x,repair_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == repair_point){
			repair_index = k;
			break;
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = IS_STOP.find(tmp_node);

		if(at != IS_STOP.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",total_length-can_supply);

	return 0;
}
accuracy: 0.0684931506849315
time_ms: 50
memory_kb: 10108
final_rank: 20

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		x_int = y_int = 0;
	}

	Point(){
		x = y = 0.0;
		x_int = y_int = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
	int x_int,y_int;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point && index == arg.index;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index,repair_index;
vector<Info> on_segment[NUM],NODES;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<pair<int,int>,int> MAP;
map<pair<int,int>,bool> USED, STOP_VALVE;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}


double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}


double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//★★点と線分の距離★★
double getDistanceSP(Line l,Point p){
	if(dot(l.p[1]-l.p[0],p-l.p[0]) < 0.0) return abs(p-l.p[0]);
	if(dot(l.p[0]-l.p[1],p-l.p[1]) < 0.0) return abs(p-l.p[1]);
	return getDistanceLP(l,p);
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&water_pipe[i].p[0].x_int,&water_pipe[i].p[0].y_int,&water_pipe[i].p[1].x_int,&water_pipe[i].p[1].y_int);


		water_pipe[i].p[0].x = water_pipe[i].p[0].x_int;
		water_pipe[i].p[0].y = water_pipe[i].p[0].y_int;
		water_pipe[i].p[1].x = water_pipe[i].p[1].x_int;
		water_pipe[i].p[1].y = water_pipe[i].p[1].y_int;

		//端点を登録
		auto at = MAP.find(make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),num_nodes));
			NODES.push_back(Info(Point(water_pipe[i].p[0]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)]));
		}

		at =  MAP.find(make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),num_nodes));
			NODES.push_back(Info(Point(water_pipe[i].p[1]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)]));
		}
	}

	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);

		//接触している線分を調べる
		Point tmp_point = Point((double)x,(double)y);
		tmp_point.x_int = x;
		tmp_point.y_int = y;

		vector<int> TMP;

		for(int k = 0; k < N; k++){

			if(fabs(getDistanceSP(water_pipe[k],tmp_point)) < EPS){
				TMP.push_back(k);
			}
		}

		auto at = MAP.find(make_pair(x,y));

		if(at == MAP.end()){

			MAP[make_pair(x,y)] = num_nodes++;
			NODES.push_back(Info(tmp_point,MAP[make_pair(x,y)]));

			for(int a = 0; a < TMP.size(); a++){

				on_segment[TMP[a]].push_back(Info(tmp_point,MAP[make_pair(x,y)])); //初登場の場合のみpushする
			}


		}
		STOP_VALVE[make_pair(x,y)] = true; //座標で、止水バルブかどうか分るようにする
	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);

	start_index = -1;

	auto at = MAP.find(make_pair(start_x,start_y));

	if(at == MAP.end()){

		start_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)start_x,(double)start_y);
		NODES.push_back(Info(tmp_point,start_index));

		for(int i = 0; i < N; i++){

			if(getDistanceSP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,start_index));
			}
		}

	}else{

		start_index = MAP[make_pair(start_x,start_y)];
	}


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);

	at = MAP.find(make_pair(repair_x,repair_y));

	if(at == MAP.end()){

		repair_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)repair_x,(double)repair_y);
		NODES.push_back(Info(tmp_point,repair_index));

		for(int i = 0; i < N; i++){

			if(getDistanceSP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,repair_index));
			}
		}
	}else{

		repair_index = MAP[make_pair(repair_x,repair_y)];
	}
	//パイプとパイプの交点ノードの座標を求める[★★MAPに登録できないので注意★★]

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			tmp_point.x_int = BIG_NUM;

			int tmp_index = -1;

			if((tmp_point == water_pipe[i].p[0] || tmp_point == water_pipe[i].p[1]) &&
					(tmp_point == water_pipe[k].p[0] || tmp_point == water_pipe[k].p[1]))continue;


			//★★交点が既に登場済の場合がある★★
			for(int a = 0; a < NODES.size(); a++){

				if(NODES[a].cross_point == tmp_point){

					tmp_index = NODES[a].index;
					break;
				}
			}

			if(tmp_index == -1){

				tmp_index = num_nodes;
				NODES.push_back(Info(tmp_point,tmp_index));
				num_nodes++;
			}
			on_segment[i].push_back(Info(tmp_point,tmp_index));
			on_segment[k].push_back(Info(tmp_point,tmp_index));
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = STOP_VALVE.find(make_pair(NODES[tmp_node].cross_point.x,NODES[tmp_node].cross_point.y));

		if(at != STOP_VALVE.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",must_stop+(total_length-(must_stop)-can_supply));

	return 0;
}
accuracy: 0.8493150684931506
time_ms: 80
memory_kb: 10824
final_rank: 12

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point && index == arg.index;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index = -1,repair_index = -1;
vector<Info> on_segment[NUM];
vector<Point> NODES,STOP_VALVE;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<int,bool> IS_STOP;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf %lf",&water_pipe[i].p[0].x,&water_pipe[i].p[0].y,&water_pipe[i].p[1].x,&water_pipe[i].p[1].y);
		NODES.push_back(Point(water_pipe[i].p[0]));
		NODES.push_back(Point(water_pipe[i].p[1]));
	}

	double x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%lf %lf",&x,&y);
		NODES.push_back(Point(x,y));
		STOP_VALVE.push_back(Point(x,y));
	}

	double start_x,start_y;

	scanf("%lf %lf",&start_x,&start_y);
	NODES.push_back(Point(start_x,start_y));


	double repair_x,repair_y;

	scanf("%lf %lf",&repair_x,&repair_y);
	NODES.push_back(Point(repair_x,repair_y));

	//パイプとパイプの交点ノードの座標を求める

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			NODES.push_back(tmp_point);
		}
	}

	sort(NODES.begin(),NODES.end());
	NODES.erase(unique(NODES.begin(),NODES.end()));

	//線分と接触しているノードを線分に所属させる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < NODES.size(); k++){
			if(getDistanceLP(water_pipe[i],NODES[k]) > EPS)continue;

			on_segment[i].push_back(Info(NODES[k],k));
		}
	}

	//止水バルブのインデックスを求める
	for(int i = 0; i < STOP_VALVE.size(); i++){

		for(int k = 0; k < NODES.size(); k++){
			if(NODES[k] == STOP_VALVE[i]){
				IS_STOP[k] = true;
				break;
			}
		}
	}

	//スタートノードのインデックスを求める
	Point start_point = Point(start_x,start_y);
	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == start_point){
			start_index = k;
			break;
		}
	}

	//修理ポイントのインデックスを求める
	Point repair_point = Point(repair_x,repair_y);

	for(int k = 0; k < NODES.size(); k++){
		if(NODES[k] == repair_point){
			repair_index = k;
			break;
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = IS_STOP.find(tmp_node);

		if(at != IS_STOP.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",must_stop+(total_length-(must_stop)-can_supply));

	return 0;
}
accuracy: 0.2054794520547945
time_ms: 40
memory_kb: 10236
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		x_int = y_int = 0;
	}

	Point(){
		x = y = 0.0;
		x_int = y_int = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
	int x_int,y_int;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point && index == arg.index;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index,repair_index;
vector<Info> on_segment[NUM],CROSS;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<pair<int,int>,int> MAP;
map<int,bool> STOP_VALVE;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&water_pipe[i].p[0].x_int,&water_pipe[i].p[0].y_int,&water_pipe[i].p[1].x_int,&water_pipe[i].p[1].y_int);


		water_pipe[i].p[0].x = water_pipe[i].p[0].x_int;
		water_pipe[i].p[0].y = water_pipe[i].p[0].y_int;
		water_pipe[i].p[1].x = water_pipe[i].p[1].x_int;
		water_pipe[i].p[1].y = water_pipe[i].p[1].y_int;

		//端点を登録
		auto at = MAP.find(make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)]));
		}

		at =  MAP.find(make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)]));
		}
	}

	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);

		//接触している線分を調べる
		Point tmp_point = Point((double)x,(double)y);
		tmp_point.x_int = x;
		tmp_point.y_int = y;

		int tmp_index;

		for(int k = 0; k < N; k++){

			if(fabs(getDistanceLP(water_pipe[k],tmp_point)) < EPS){
				tmp_index = k;
				break;
			}
		}

		auto at = MAP.find(make_pair(x,y));

		if(at == MAP.end()){

			MAP[make_pair(x,y)] = num_nodes++;
			on_segment[tmp_index].push_back(Info(tmp_point,MAP[make_pair(x,y)])); //初登場の場合のみpushする
		}
		STOP_VALVE[MAP[make_pair(x,y)]] = true; //ノード番号で、止水バルブかどうか分るようにする
	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);

	start_index = -1;

	auto at = MAP.find(make_pair(start_x,start_y));

	if(at == MAP.end()){

		start_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)start_x,(double)start_y);

		for(int i = 0; i < N; i++){

			if(getDistanceLP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,start_index));
				break;
			}
		}

	}else{

		start_index = MAP[make_pair(start_x,start_y)];
	}


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);

	at = MAP.find(make_pair(repair_x,repair_y));

	if(at == MAP.end()){

		repair_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)repair_x,(double)repair_y);

		for(int i = 0; i < N; i++){

			if(getDistanceLP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,repair_index));
				break;
			}
		}

	}else{

		repair_index = MAP[make_pair(repair_x,repair_y)];
	}


	//パイプとパイプの交点ノードの座標を求める[★★MAPに登録できないので注意★★]

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			tmp_point.x_int = BIG_NUM;

			if((tmp_point == water_pipe[i].p[0] || tmp_point == water_pipe[i].p[1]) &&
					(tmp_point == water_pipe[k].p[0] || tmp_point == water_pipe[k].p[1]))continue;

			int tmp_index = -1;
			//★★交点が既に登場済の場合がある★★
			//if((tmp_point == water_pipe[i].p[0] || tmp_point == water_pipe[i].p[1]) ){

				for(int a = 0; a < on_segment[i].size(); a++){
					if(on_segment[i][a].cross_point == tmp_point){
						tmp_index = on_segment[i][a].index;
						break;
					}
				}

				if(tmp_index != -1){
					on_segment[k].push_back(Info(tmp_point,tmp_index));
					continue;
				}

			//}else if((tmp_point == water_pipe[k].p[0] || tmp_point == water_pipe[k].p[1])){

				for(int a = 0; a < on_segment[k].size(); a++){
					if(on_segment[k][a].cross_point == tmp_point){
						tmp_index = on_segment[k][a].index;
						break;
					}
				}
				if(tmp_index != -1){

					on_segment[i].push_back(Info(tmp_point,tmp_index));
					continue;
				}
			//}

			//if(tmp_index != -1)continue;


			//既に登場済みでないか探す

			for(int a = 0; a < CROSS.size(); a++){

				if(CROSS[a].cross_point == tmp_point){

					tmp_index = CROSS[a].index;
					break;
				}
			}
			if(tmp_index == -1){

				CROSS.push_back(Info(tmp_point,num_nodes));
				tmp_index = num_nodes;
				num_nodes++;
			}
			on_segment[i].push_back(Info(tmp_point,tmp_index));
			on_segment[k].push_back(Info(tmp_point,tmp_index));
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = STOP_VALVE.find(tmp_node);

		if(at != STOP_VALVE.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",must_stop+(total_length-(must_stop)-can_supply));

	return 0;
}
accuracy: 0.4794520547945205
time_ms: 70
memory_kb: 10880
final_rank: 14

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 305

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		x_int = y_int = 0;
	}

	Point(){
		x = y = 0.0;
		x_int = y_int = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
	int x_int,y_int;
};
typedef Point Vector;

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){
	}
};

struct Info{
	Info(Point arg_cross_point,int arg_index){

		cross_point.x = arg_cross_point.x;
		cross_point.y = arg_cross_point.y;
		index = arg_index;
	}
	bool operator<(const struct Info &arg) const{
		return cross_point < arg.cross_point;
	}
	bool operator==(const struct Info &arg) const{
		return cross_point == arg.cross_point && index == arg.index;
	}

	Point cross_point;
	int index;
};

struct Edge{
	Edge(int arg_to, double arg_cost){

		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

int N,M;
int num_nodes;
int start_index,repair_index;
vector<Info> on_segment[NUM],CROSS;
Point start,goal;
Line water_pipe[NUM];
vector<Edge> G[NUM*NUM];
map<pair<int,int>,int> MAP;
map<int,bool> STOP_VALVE;
map<pair<int,int>,bool> USED;


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}




double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

int main(){


	scanf("%d %d",&N,&M);

	num_nodes = 0;

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&water_pipe[i].p[0].x_int,&water_pipe[i].p[0].y_int,&water_pipe[i].p[1].x_int,&water_pipe[i].p[1].y_int);


		water_pipe[i].p[0].x = water_pipe[i].p[0].x_int;
		water_pipe[i].p[0].y = water_pipe[i].p[0].y_int;
		water_pipe[i].p[1].x = water_pipe[i].p[1].x_int;
		water_pipe[i].p[1].y = water_pipe[i].p[1].y_int;

		//端点を登録
		auto at = MAP.find(make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[0]),MAP[make_pair(water_pipe[i].p[0].x_int,water_pipe[i].p[0].y_int)]));
		}

		at =  MAP.find(make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int));
		if(at == MAP.end()){

			MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)] = num_nodes;
			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),num_nodes));
			num_nodes++;

		}else{

			on_segment[i].push_back(Info(Point(water_pipe[i].p[1]),MAP[make_pair(water_pipe[i].p[1].x_int,water_pipe[i].p[1].y_int)]));
		}
	}

	int x,y;

	//止水バルブの取得

	for(int i = 0; i < M; i++){

		scanf("%d %d",&x,&y);

		//接触している線分を調べる
		Point tmp_point = Point((double)x,(double)y);
		tmp_point.x_int = x;
		tmp_point.y_int = y;

		int tmp_index;

		for(int k = 0; k < N; k++){

			if(fabs(getDistanceLP(water_pipe[k],tmp_point)) < EPS){
				tmp_index = k;
				break;
			}
		}

		auto at = MAP.find(make_pair(x,y));

		if(at == MAP.end()){

			MAP[make_pair(x,y)] = num_nodes++;
			on_segment[tmp_index].push_back(Info(tmp_point,MAP[make_pair(x,y)])); //初登場の場合のみpushする
		}
		STOP_VALVE[MAP[make_pair(x,y)]] = true; //ノード番号で、止水バルブかどうか分るようにする
	}

	int start_x,start_y;

	scanf("%d %d",&start_x,&start_y);

	start_index = -1;

	auto at = MAP.find(make_pair(start_x,start_y));

	if(at == MAP.end()){

		start_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)start_x,(double)start_y);

		for(int i = 0; i < N; i++){

			if(getDistanceLP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,start_index));
				break;
			}
		}

	}else{

		start_index = MAP[make_pair(start_x,start_y)];
	}


	int repair_x,repair_y;

	scanf("%d %d",&repair_x,&repair_y);

	at = MAP.find(make_pair(repair_x,repair_y));

	if(at == MAP.end()){

		repair_index = num_nodes++;

		//接触している線分を調べる
		Point tmp_point = Point((double)repair_x,(double)repair_y);

		for(int i = 0; i < N; i++){

			if(getDistanceLP(water_pipe[i],tmp_point) < EPS){
				on_segment[i].push_back(Info(tmp_point,repair_index));
				break;
			}
		}

	}else{

		repair_index = MAP[make_pair(repair_x,repair_y)];
	}


	//パイプとパイプの交点ノードの座標を求める[★★MAPに登録できないので注意★★]

	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			if(!is_Cross(water_pipe[i],water_pipe[k]))continue;

			Point tmp_point = calc_Cross_Point(water_pipe[i],water_pipe[k]);
			tmp_point.x_int = BIG_NUM;

			if((tmp_point == water_pipe[i].p[0] || tmp_point == water_pipe[i].p[1]) &&
					(tmp_point == water_pipe[k].p[0] || tmp_point == water_pipe[k].p[1]))continue;

			int tmp_index = -1;
			//★★交点が既に登場済の場合がある★★
			if((tmp_point == water_pipe[i].p[0] || tmp_point == water_pipe[i].p[1]) ){

				for(int a = 0; a < on_segment[i].size(); a++){
					if(on_segment[i][a].cross_point == tmp_point){
						tmp_index = on_segment[i][a].index;
						break;
					}
				}

				on_segment[k].push_back(Info(tmp_point,tmp_index));

			}else if((tmp_point == water_pipe[k].p[0] || tmp_point == water_pipe[k].p[1])){

				for(int a = 0; a < on_segment[k].size(); a++){
					if(on_segment[k][a].cross_point == tmp_point){
						tmp_index = on_segment[k][a].index;
						break;
					}
				}

				on_segment[i].push_back(Info(tmp_point,tmp_index));
			}

			if(tmp_index != -1)continue;


			//既に登場済みでないか探す

			for(int a = 0; a < CROSS.size(); a++){

				if(CROSS[a].cross_point == tmp_point){

					tmp_index = CROSS[a].index;
					break;
				}
			}
			if(tmp_index == -1){

				CROSS.push_back(Info(tmp_point,num_nodes));
				tmp_index = num_nodes;
				num_nodes++;
			}
			on_segment[i].push_back(Info(tmp_point,tmp_index));
			on_segment[k].push_back(Info(tmp_point,tmp_index));
		}
	}

	double total_length = 0;

	//グラフを作成
	for(int i = 0; i < N; i++){

		sort(on_segment[i].begin(),on_segment[i].end());
		on_segment[i].erase(unique(on_segment[i].begin(),on_segment[i].end()),on_segment[i].end());

		for(int k = 1; k < on_segment[i].size(); k++){

			int from = on_segment[i][k-1].index;
			int to = on_segment[i][k].index;

			double tmp_dist = calc_dist(on_segment[i][k-1].cross_point,on_segment[i][k].cross_point);

			total_length += tmp_dist;

			G[from].push_back(Edge(to,tmp_dist));
			G[to].push_back(Edge(from,tmp_dist));
		}
	}

	double must_stop = 0;

	//修理ポイントから、止水バルブを通らずに行ける範囲の距離を求める[★必ず止める★]
	queue<int> Q;
	Q.push(repair_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		auto at = STOP_VALVE.find(tmp_node);

		if(at != STOP_VALVE.end()){ //tmp_nodeは止水バルブ

			continue;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));

			if(at != USED.end())continue; //エッジを通過済み

			if(next_node == start_index){

				printf("-1\n"); //水源から修理点までの間に止水バルブがないので不可
				return 0;
			}

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			must_stop += G[tmp_node][i].cost;

			Q.push(next_node);
		}
	}

	//水源から、水を停めた範囲を通らずに、水を供給できる範囲を求める
	double can_supply = 0;

	Q.push(start_index);

	while(!Q.empty()){

		int tmp_node = Q.front();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			int next_node = G[tmp_node][i].to;

			auto at = USED.find(make_pair(tmp_node,next_node));
			if(at != USED.end())continue; //エッジを通過済み

			can_supply += G[tmp_node][i].cost;

			USED[make_pair(tmp_node,next_node)] = true;
			USED[make_pair(next_node,tmp_node)] = true;

			Q.push(next_node);
		}
	}

	printf("%.10lf\n",must_stop+(total_length-(must_stop)-can_supply));

	return 0;
}
accuracy: 0.4794520547945205
time_ms: 70
memory_kb: 10832
final_rank: 13

code_snippet: #include <cmath>
#include <vector>
#include <algorithm>

class point2d {
public:
	double x, y;
	point2d() : x(0), y(0) {};
	point2d(double x_, double y_) : x(x_), y(y_) {};
	bool operator==(const point2d& p) { return x == p.x && y == p.y; }
	bool operator!=(const point2d& p) { return x != p.x || y != p.y; }
	point2d& operator+=(const point2d& p) { x += p.x; y += p.y; return *this; }
	point2d& operator-=(const point2d& p) { x -= p.x; y -= p.y; return *this; }
	point2d& operator*=(const double v) { x *= v; y *= v; return *this; }
	point2d operator+(const point2d& p) const { return point2d(*this) += p; }
	point2d operator-(const point2d& p) const { return point2d(*this) -= p; }
	point2d operator*(const double v) const { return point2d(*this) *= v; }
	double norm() const { return x * x + y * y; }
	double abs() const { return std::sqrt(x * x + y * y); }
	double dot(const point2d& p) const { return x * p.x + y * p.y; }
	double cross(const point2d& p) const { return x * p.y - y * p.x; }
	int ccw(const point2d& p1, const point2d& p2) const {
		// RETURNS: P0 -> P1 -> P2 IS COLLINEAR --> ((P0, P1, P2) IS CENTER --> (2, -2, 0)), COUNTER-CLOCKWISE --> 1, CLOCKWISE --> -1
		point2d pr1 = p1 - point2d(*this);
		point2d pr2 = p2 - point2d(*this);
		if (pr1.cross(pr2) != 0) return pr1.cross(pr2) > 0 ? 1 : -1;
		if (pr1.dot(pr2) < 0) return 2;
		return pr1.norm() < pr2.norm() ? -2 : 0;
	}
};
class segment2d {
public:
	point2d p1, p2;
	segment2d() : p1(point2d()), p2(point2d()) {};
	segment2d(const point2d& p1_, const point2d& p2_) : p1(p1_), p2(p2_) {};
	double norm() const { return (p1 - p2).norm(); }
	double abs() const { return (p1 - p2).abs(); }
};

bool intersect(const segment2d& s1, const segment2d& s2) {
	return s1.p1.ccw(s1.p2, s2.p1) * s1.p1.ccw(s1.p2, s2.p2) <= 0 && s2.p1.ccw(s2.p2, s1.p1) * s2.p1.ccw(s2.p2, s1.p2) <= 0;
}
point2d intersect_point(const segment2d& s1, const segment2d& s2) {
	point2d base = s2.p2 - s2.p1;
	double d1 = std::abs(base.cross(s1.p1 - s2.p1));
	double d2 = std::abs(base.cross(s1.p2 - s2.p1));
	return s1.p1 + (s1.p2 - s1.p1) * (d1 / (d1 + d2));
}
double distance(const point2d& p, const segment2d& s) {
	double d1 = (p - s.p1).norm();
	double d2 = (p - s.p2).norm();
	double d0 = s.norm();
	if (d0 + d1 < d2 || d0 + d2 < d1) return std::sqrt(std::min(d1, d2));
	return std::abs((p - s.p1).cross(s.p2 - s.p1)) / std::sqrt(d0);
}

#include <queue>
#include <iostream>
#include <functional>
using namespace std;
struct edge {
	int to, id;
};
int main() {
	int N, M;
	cin >> N >> M;
	vector<segment2d> seg(N);
	for (int i = 0; i < N; ++i) {
		cin >> seg[i].p1.x >> seg[i].p1.y >> seg[i].p2.x >> seg[i].p2.y;
	}
	vector<point2d> valve(M);
	for (int i = 0; i < M; ++i) {
		cin >> valve[i].x >> valve[i].y;
	}
	point2d src, dst;
	cin >> src.x >> src.y >> dst.x >> dst.y;
	vector<vector<int> > cardinals(N);
	vector<point2d> pts;
	vector<int> ptstype;
	function<int(point2d)> next_ptr = [&](point2d p) {
		for (int i = 0; i < pts.size(); ++i) {
			if ((p - pts[i]).abs() < 1.0e-8) return i;
		}
		return int(pts.size());
	};
	for (int i = 0; i < N; ++i) {
		int p1ptr = next_ptr(seg[i].p1);
		if (p1ptr == pts.size()) pts.push_back(seg[i].p1), ptstype.push_back(0);
		cardinals[i].push_back(p1ptr);
		ptstype[p1ptr] |= 1;
		int p2ptr = next_ptr(seg[i].p2);
		if (p2ptr == pts.size()) pts.push_back(seg[i].p2), ptstype.push_back(0);
		cardinals[i].push_back(p2ptr);
		ptstype[p1ptr] |= 1;
	}
	for (int i = 0; i < M; ++i) {
		int ptr = next_ptr(valve[i]);
		if (ptr == pts.size()) pts.push_back(valve[i]), ptstype.push_back(0);
		ptstype[ptr] |= 2;
		for (int j = 0; j < N; ++j) {
			if (distance(valve[i], seg[j]) < 1.0e-8) {
				cardinals[j].push_back(ptr);
			}
		}
	}
	int srcptr = next_ptr(src);
	if (srcptr == pts.size()) pts.push_back(src), ptstype.push_back(0);
	ptstype[srcptr] |= 4;
	int dstptr = next_ptr(dst);
	if (dstptr == pts.size()) pts.push_back(dst), ptstype.push_back(0);
	ptstype[dstptr] |= 8;
	for (int i = 0; i < N; ++i) {
		if (distance(src, seg[i]) < 1.0e-8) {
			cardinals[i].push_back(srcptr);
		}
		if (distance(dst, seg[i]) < 1.0e-8) {
			cardinals[i].push_back(dstptr);
		}
	}
	for (int i = 0; i < N; ++i) {
		for (int j = i + 1; j < N; ++j) {
			if (intersect(seg[i], seg[j])) {
				point2d crp = intersect_point(seg[i], seg[j]);
				int ptr = next_ptr(crp);
				if (ptr == pts.size()) pts.push_back(crp), ptstype.push_back(0);
				ptstype[ptr] |= 16;
				cardinals[i].push_back(ptr);
				cardinals[j].push_back(ptr);
			}
		}
	}
	vector<vector<edge> > G(pts.size());
	int cnt = 0;
	for (int i = 0; i < N; ++i) {
		sort(cardinals[i].begin(), cardinals[i].end(), [&](int j, int k) { return abs(pts[j].x - pts[k].x) > 1.0e-8 ? pts[j].x < pts[k].x : pts[j].y < pts[k].y; });
		cardinals[i].erase(unique(cardinals[i].begin(), cardinals[i].end()), cardinals[i].end());
		for (int j = 1; j < cardinals[i].size(); ++j) {
			G[cardinals[i][j]].push_back(edge{ cardinals[i][j - 1], cnt });
			G[cardinals[i][j - 1]].push_back(edge{ cardinals[i][j], cnt });
			++cnt;
		}
	}
	queue<int> que;
	que.push(dstptr);
	vector<bool> used(pts.size());
	used[dstptr] = true;
	while (!que.empty()) {
		int u = que.front(); que.pop();
		if (ptstype[u] & 2) continue;
		for (edge &e : G[u]) {
			if (!used[e.to]) {
				used[e.to] = true;
				que.push(e.to);
			}
		}
	}
	vector<bool> pass(pts.size());
	vector<bool> usededge(cnt);
	que.push(srcptr);
	pass[srcptr] = true;
	while (!que.empty()) {
		int u = que.front(); que.pop();
		if ((ptstype[u] & 2) && used[u]) continue;
		for (edge& e : G[u]) {
			usededge[e.id] = true;
			if (!pass[e.to]) {
				pass[e.to] = true;
				que.push(e.to);
			}
		}
	}
	if (pass[dstptr]) cout << -1 << endl;
	else {
		double sum = 0.0;
		for (int i = 0; i < pts.size(); ++i) {
			for (edge e : G[i]) {
				if (!usededge[e.id]) {
					sum += (pts[i] - pts[e.to]).abs();
					usededge[e.id] = true;
				}
			}
		}
		cout.precision(15);
		cout << fixed << sum << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 4500
final_rank: 2

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    const static bool comp(const P &p1,const P &p2){return p1.real()==p2.real()?p1.imag()<p2.imag():p1.real()<p2.real();}
    
    static bool comp_y(const P &p1,const P &p2){return p1.imag()==p2.imag()?p1.real()<p2.real():p1.imag()<p2.imag();}
    
    static bool eqls(const P &p1,const P &p2){return abs(p1-p2)<EPS;}
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){vec/=abs(vec); p1/=vec; p2/=vec; return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);}
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){return (dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS) || (dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS)?false:intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);}
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){return dot(p2-p1,x-p1)<-EPS?abs(x-p1):dot(p1-p2,x-p2)<-EPS?abs(x-p2):distLP(p1,p2,x);}
    
    D distSS(P p1,P p2,P p3,P p4){return intersectSS(p1,p2,p3,p4)?0.0:min(min(distSP(p1,p2,p3),distSP(p1,p2,p4)),min(distSP(p3,p4,p1),distSP(p3,p4,p2)));}
    
    P crosspointLL(P p1,P p2,P vec){return abs(cross(p2-p1,vec))<EPS?vec:vec*cross(p2-p1,p2)/cross(p2-p1,vec);}
    
    P crosspointLL(P p1,P p2,P p3,P p4){return p4+crosspointLL(p1-p4,p2-p4,p3-p4);}
    
    P crosspointSS(P p1,P p2,P p3,P p4){return distSP(p1,p2,p3)<EPS?p3:distSP(p1,p2,p4)<EPS?p4:crosspointLL(p1,p2,p3,p4);}
    
    bool intersectShL(P p1,P p2,P vec){vec/=abs(vec); return intersectSL(p1,p2,vec) && crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;}
    
    bool intersectShL(P p1,P p2,P p3,P p4){return intersectShL(p1-p3,p2-p3,p4-p3);}
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        vector<bool> cnt(5,false);
        for(int i=1;i<=poly.size();i++){
            if(distSP(poly[i-1],poly[i%poly.size()],p)<EPS){return 0;}
            for(int j=0;j<5;j++){
                if(intersectShL(poly[i-1],poly[i%poly.size()],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<5;j++){if(cnt[j]){in++;}}
        return in>=3?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=1;i<=poly.size();i++){
            if(cross(p2-p1,poly[i-1]-p1)>-EPS){ret.push_back(poly[i-1]);}
            if(intersectSL(poly[i-1],poly[i%poly.size()],p1,p2) && distLP(p1,p2,poly[i-1])>EPS && distLP(p1,p2,poly[i%poly.size()])>EPS){ret.push_back(crosspointLL(poly[i-1],poly[i%poly.size()],p1,p2));}
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<poly.size();i++){ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);}
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        for(auto &I:pts){
            if(!ret.empty() && I==ret.back()){continue;}
            while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){ret.pop_back();}
            ret.push_back(I);
        }
        reverse(pts.begin(),pts.end());
        for(auto &I:pts){
            if(!ret.empty() && I==ret.back()){continue;}
            while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){ret.pop_back();}
            ret.push_back(I);
        }
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){if(distSP(p1,p2,I)<EPS){ret.push_back(I);}}
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));}
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        for(ll i=1;i<pt.size();i<<=1){
            for(ll j=0;i+j<pt.size();j+=i*2){
                ll m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(ll k=j;k<m;k++){l=max(l,pt[k].real());}
                for(ll k=0;m+k<pt.size() && k<i;k++){r=min(r,pt[m+k].real());}
                for(ll k=0;m+k<pt.size() && k<i;k++){if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}}
                ll idx=0;
                for(ll k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    while(idx<R.size() && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(ll n=idx;n<R.size() && R[n].imag()-pt[k].imag()<ret;n++){ret=min(ret,abs(R[n]-pt[k]));}
                }
                inplace_merge(pt.begin()+j,pt.begin()+m,j+i*2<pt.size()?pt.begin()+j+2*i:pt.end(),comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=(int)L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto le=[](P a,P b){return eqls(a,b)?false:comp(a,b);};
        sort(pt.begin(),pt.end(),le);
        pt.erase(unique(pt.begin(),pt.end(),eqls),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || eqls(pt[v],pt[pre])?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};

using namespace Geometry;



int main(){
    cout<<fixed<<setprecision(15);
    ll N,M;
    cin>>N>>M;
    vector<pair<P,P>> A(N);
    cin>>A;
    vector<P> B(M);
    cin>>B;
    P s,t;
    cin>>s>>t;
    vector<P> pt=B;
    pt.push_back(s);
    pt.push_back(t);
    vector<pair<int,int>> seg;
    segment_arrangement(A,seg,pt);
    vector<vector<int>> edge(pt.size());
    for(auto &I:seg){
        edge[I.F].push_back(I.S);
        edge[I.S].push_back(I.F);
    }
    vector<bool> used(pt.size(),false);
    vector<bool> closed(pt.size(),false);
    vector<bool> bulb(pt.size(),false);
    for(auto &I:B){
        for(int j=0;j<pt.size();j++){
            if(abs(I-pt[j])<EPS){bulb[j]=true;}
        }
    }
    function<void(int)> dfs=[&](int v){
        if(bulb[v]){closed[v]=true; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-t)<EPS){dfs(i);}
    }
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS && used[i]){
            cout<<-1<<endl;
            return 0;
        }
    }
    for(int i=0;i<pt.size();i++){used[i]=false;}
    function<void(int)> dfs2=[&](int v){
        if(closed[v]){used[v]=false; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs2(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS){used[i]=true; dfs2(i);}
    }
    D sum=0;
    for(auto &I:seg){
        if(!used[I.F] && !used[I.S]){sum+=abs(pt[I.F]-pt[I.S]);}
    }
    cout<<sum<<endl;
    
    
    return 0;
}
accuracy: 1
time_ms: 790
memory_kb: 4984
final_rank: 5

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    static bool comp(const P &p1,const P &p2){
        if(p1.real()==p2.real()){return p1.imag()<p2.imag();}
        return p1.real()<p2.real();
    }
    
    static bool comp_y(const P &p1,const P &p2){
        if(p1.imag()==p2.imag()){return p1.real()<p2.real();}
        return p1.imag()<p2.imag();
    }
    
    static bool eqls(const P &p1,const P &p2){return abs(p1-p2)<EPS;}
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){
        vec/=abs(vec); p1/=vec; p2/=vec;
        return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);
    }
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){
        if(dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS){return false;}
        if(dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS){return false;}
        return intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);
    }
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){
        if(dot(p2-p1,x-p1)<-EPS){return abs(x-p1);}
        if(dot(p1-p2,x-p2)<-EPS){return abs(x-p2);}
        return distLP(p1,p2,x);
    }
    
    D distSS(P p1,P p2,P p3,P p4){
        if(intersectSS(p1,p2,p3,p4)){return 0.0;}
        return min({distSP(p1,p2,p3),distSP(p1,p2,p4),
            distSP(p3,p4,p1),distSP(p3,p4,p2)});
    }
    
    P crosspointLL(P p1,P p2,P vec){
        if(abs(cross(p2-p1,vec))<EPS){return vec;}
        return vec*cross(p2-p1,p2)/cross(p2-p1,vec);
    }
    
    P crosspointLL(P p1,P p2,P p3,P p4){
        return p4+crosspointLL(p1-p4,p2-p4,p3-p4);
    }
    
    P crosspointSS(P p1,P p2,P p3,P p4){
        if(distSP(p1,p2,p3)<EPS){return p3;}
        if(distSP(p1,p2,p4)<EPS){return p4;}
        return crosspointLL(p1,p2,p3,p4);
    }
    
    bool intersectShL(P p1,P p2,P vec){
        vec/=abs(vec);
        return intersectSL(p1,p2,vec) &&
        crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;
    }
    
    bool intersectShL(P p1,P p2,P p3,P p4){
        return intersectShL(p1-p3,p2-p3,p4-p3);
    }
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        int s=A.size();
        vector<bool> cnt(s,false);
        for(int i=0;i<(int)poly.size();i++){
            int k=(i+1)%poly.size();
            if(distSP(poly[i],poly[k],p)<EPS){return 0;}
            for(int j=0;j<s;j++){
                if(intersectShL(poly[i],poly[k],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<s;j++){if(cnt[j]){in++;}}
        return in>s/2?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=0;i<(int)poly.size();i++){
            int j=(i+1)%poly.size();
            if(cross(p2-p1,poly[i]-p1)>-EPS){ret.push_back(poly[i]);}
            if(intersectSL(poly[i],poly[j],p1,p2) &&
               distLP(p1,p2,poly[i])>EPS && distLP(p1,p2,poly[j])>EPS){
                ret.push_back(crosspointLL(poly[i],poly[j],p1,p2));
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<(int)poly.size();i++){
            ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);
        }
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        auto fnc=[&](){
            for(auto &I:pts){
                if(!ret.empty() && I==ret.back()){continue;}
                while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){
                    ret.pop_back();
                }
                ret.push_back(I);
            }
        };
        fnc();
        reverse(pts.begin(),pts.end());
        fnc();
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){
            if(distSP(p1,p2,I)<EPS){ret.push_back(I);}
        }
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){
        return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));
    }
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<(int)poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        int N=pt.size();
        for(int i=1;i<N;i<<=1){
            for(int j=0;i+j<N;j+=i*2){
                int m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(int k=j;k<m;k++){l=max(l,pt[k].real());}
                for(int k=0;m+k<N && k<i;k++){r=min(r,pt[m+k].real());}
                for(int k=0;m+k<N && k<i;k++){
                    if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}
                }
                int idx=0;
                for(int k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    int M=R.size();
                    while(idx<M && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(int s=idx;s<M && R[s].imag()-pt[k].imag()<ret;s++){
                        ret=min(ret,abs(R[s]-pt[k]));
                    }
                }
                auto ed=(j+i*2<N?pt.begin()+j+2*i:pt.end());
                inplace_merge(pt.begin()+j,pt.begin()+m,ed,comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<(int)pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=(int)L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto le=[](P a,P b){return eqls(a,b)?false:comp(a,b);};
        sort(pt.begin(),pt.end(),le);
        pt.erase(unique(pt.begin(),pt.end(),eqls),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || eqls(pt[v],pt[pre])?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};

using namespace Geometry;



int main(){
    cout<<fixed<<setprecision(15);
    ll N,M;
    cin>>N>>M;
    vector<pair<P,P>> A(N);
    cin>>A;
    vector<P> B(M);
    cin>>B;
    P s,t;
    cin>>s>>t;
    vector<P> pt=B;
    pt.push_back(s);
    pt.push_back(t);
    vector<pair<int,int>> seg;
    segment_arrangement(A,seg,pt);
    vector<vector<int>> edge(pt.size());
    for(auto &I:seg){
        edge[I.F].push_back(I.S);
        edge[I.S].push_back(I.F);
    }
    vector<bool> used(pt.size(),false);
    vector<bool> closed(pt.size(),false);
    vector<bool> bulb(pt.size(),false);
    for(auto &I:B){
        for(int j=0;j<pt.size();j++){
            if(abs(I-pt[j])<EPS){bulb[j]=true;}
        }
    }
    function<void(int)> dfs=[&](int v){
        if(bulb[v]){closed[v]=true; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-t)<EPS){dfs(i);}
    }
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS && used[i]){
            cout<<-1<<endl;
            return 0;
        }
    }
    for(int i=0;i<pt.size();i++){used[i]=false;}
    function<void(int)> dfs2=[&](int v){
        if(closed[v]){used[v]=false; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs2(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS){used[i]=true; dfs2(i);}
    }
    D sum=0;
    for(auto &I:seg){
        if(!used[I.F] && !used[I.S]){sum+=abs(pt[I.F]-pt[I.S]);}
    }
    cout<<sum<<endl;
    
    
    return 0;
}
accuracy: 1
time_ms: 740
memory_kb: 4932
final_rank: 3

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    static bool comp(const P &p1,const P &p2){
        if(p1.real()==p2.real()){return p1.imag()<p2.imag();}
        return p1.real()<p2.real();
    }
    
    static bool comp_y(const P &p1,const P &p2){
        if(p1.imag()==p2.imag()){return p1.real()<p2.real();}
        return p1.imag()<p2.imag();
    }
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){
        vec/=abs(vec); p1/=vec; p2/=vec;
        return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);
    }
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){
        if(dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS){return false;}
        if(dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS){return false;}
        return intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);
    }
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){
        if(dot(p2-p1,x-p1)<-EPS){return abs(x-p1);}
        if(dot(p1-p2,x-p2)<-EPS){return abs(x-p2);}
        return distLP(p1,p2,x);
    }
    
    D distSS(P p1,P p2,P p3,P p4){
        if(intersectSS(p1,p2,p3,p4)){return 0.0;}
        return min({distSP(p1,p2,p3),distSP(p1,p2,p4),
            distSP(p3,p4,p1),distSP(p3,p4,p2)});
    }
    
    P crosspointLL(P p1,P p2,P vec){
        if(abs(cross(p2-p1,vec))<EPS){return vec;}
        return vec*cross(p2-p1,p2)/cross(p2-p1,vec);
    }
    
    P crosspointLL(P p1,P p2,P p3,P p4){
        return p4+crosspointLL(p1-p4,p2-p4,p3-p4);
    }
    
    P crosspointSS(P p1,P p2,P p3,P p4){
        if(distSP(p1,p2,p3)<EPS){return p3;}
        if(distSP(p1,p2,p4)<EPS){return p4;}
        return crosspointLL(p1,p2,p3,p4);
    }
    
    bool intersectShL(P p1,P p2,P vec){
        vec/=abs(vec);
        return intersectSL(p1,p2,vec) &&
        crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;
    }
    
    bool intersectShL(P p1,P p2,P p3,P p4){
        return intersectShL(p1-p3,p2-p3,p4-p3);
    }
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        int s=A.size();
        vector<bool> cnt(s,false);
        for(int i=0;i<(int)poly.size();i++){
            int k=(i+1)%poly.size();
            if(distSP(poly[i],poly[k],p)<EPS){return 0;}
            for(int j=0;j<s;j++){
                if(intersectShL(poly[i],poly[k],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<s;j++){if(cnt[j]){in++;}}
        return in>s/2?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=0;i<(int)poly.size();i++){
            int j=(i+1)%poly.size();
            if(cross(p2-p1,poly[i]-p1)>-EPS){ret.push_back(poly[i]);}
            if(intersectSL(poly[i],poly[j],p1,p2) &&
               distLP(p1,p2,poly[i])>EPS && distLP(p1,p2,poly[j])>EPS){
                ret.push_back(crosspointLL(poly[i],poly[j],p1,p2));
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<(int)poly.size();i++){
            ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);
        }
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        auto fnc=[&](){
            for(auto &I:pts){
                if(!ret.empty() && I==ret.back()){continue;}
                while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){
                    ret.pop_back();
                }
                ret.push_back(I);
            }
        };
        fnc();
        reverse(pts.begin(),pts.end());
        fnc();
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){
            if(distSP(p1,p2,I)<EPS){ret.push_back(I);}
        }
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){
        return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));
    }
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<(int)poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        int N=pt.size();
        for(int i=1;i<N;i<<=1){
            for(int j=0;i+j<N;j+=i*2){
                int m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(int k=j;k<m;k++){l=max(l,pt[k].real());}
                for(int k=0;m+k<N && k<i;k++){r=min(r,pt[m+k].real());}
                for(int k=0;m+k<N && k<i;k++){
                    if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}
                }
                int idx=0;
                for(int k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    int M=R.size();
                    while(idx<M && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(int s=idx;s<M && R[s].imag()-pt[k].imag()<ret;s++){
                        ret=min(ret,abs(R[s]-pt[k]));
                    }
                }
                auto ed=(j+i*2<N?pt.begin()+j+2*i:pt.end());
                inplace_merge(pt.begin()+j,pt.begin()+m,ed,comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<(int)pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=(int)L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto less=[](P a,P b){return abs(a-b)<EPS?false:comp(a,b);};
        sort(pt.begin(),pt.end(),less);
        pt.erase(unique(pt.begin(),pt.end(),[](P a,P b){return abs(a-b)<EPS;}),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || abs(pt[v]-pt[pre])<EPS?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};

using namespace Geometry;



int main(){
    cout<<fixed<<setprecision(15);
    ll N,M;
    cin>>N>>M;
    vector<pair<P,P>> A(N);
    cin>>A;
    vector<P> B(M);
    cin>>B;
    P s,t;
    cin>>s>>t;
    vector<P> pt=B;
    pt.push_back(s);
    pt.push_back(t);
    vector<pair<int,int>> seg;
    segment_arrangement(A,seg,pt);
    vector<vector<int>> edge(pt.size());
    for(auto &I:seg){
        edge[I.F].push_back(I.S);
        edge[I.S].push_back(I.F);
    }
    vector<bool> used(pt.size(),false);
    vector<bool> closed(pt.size(),false);
    vector<bool> bulb(pt.size(),false);
    for(auto &I:B){
        for(int j=0;j<pt.size();j++){
            if(abs(I-pt[j])<EPS){bulb[j]=true;}
        }
    }
    function<void(int)> dfs=[&](int v){
        if(bulb[v]){closed[v]=true; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-t)<EPS){dfs(i);}
    }
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS && used[i]){
            cout<<-1<<endl;
            return 0;
        }
    }
    for(int i=0;i<pt.size();i++){used[i]=false;}
    function<void(int)> dfs2=[&](int v){
        if(closed[v]){used[v]=false; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs2(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS){used[i]=true; dfs2(i);}
    }
    D ans=0;
    for(auto &I:seg){
        ans+=abs(pt[I.F]-pt[I.S]);
        if(used[I.F] || used[I.S]){ans-=abs(pt[I.F]-pt[I.S]);}
    }
    D sum=0;
    for(auto &I:seg){
        if(!used[I.F] && !used[I.S]){sum+=abs(pt[I.F]-pt[I.S]);}
    }
    cout<<ans<<endl;
    
    
    return 0;
}
accuracy: 1
time_ms: 740
memory_kb: 4940
final_rank: 4

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    static bool comp(const P &p1,const P &p2){
        if(p1.real()==p2.real()){return p1.imag()<p2.imag();}
        return p1.real()<p2.real();
    }
    
    static bool comp_y(const P &p1,const P &p2){
        if(p1.imag()==p2.imag()){return p1.real()<p2.real();}
        return p1.imag()<p2.imag();
    }
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){
        vec/=abs(vec); p1/=vec; p2/=vec;
        return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);
    }
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){
        if(dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS){return false;}
        if(dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS){return false;}
        return intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);
    }
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){
        if(dot(p2-p1,x-p1)<-EPS){return abs(x-p1);}
        if(dot(p1-p2,x-p2)<-EPS){return abs(x-p2);}
        return distLP(p1,p2,x);
    }
    
    D distSS(P p1,P p2,P p3,P p4){
        if(intersectSS(p1,p2,p3,p4)){return 0.0;}
        return min({distSP(p1,p2,p3),distSP(p1,p2,p4),
            distSP(p3,p4,p1),distSP(p3,p4,p2)});
    }
    
    P crosspointLL(P p1,P p2,P vec){
        if(abs(cross(p2-p1,vec))<EPS){return vec;}
        return vec*cross(p2-p1,p2)/cross(p2-p1,vec);
    }
    
    P crosspointLL(P p1,P p2,P p3,P p4){
        return p4+crosspointLL(p1-p4,p2-p4,p3-p4);
    }
    
    P crosspointSS(P p1,P p2,P p3,P p4){
        if(distSP(p1,p2,p3)<EPS){return p3;}
        if(distSP(p1,p2,p4)<EPS){return p4;}
        return crosspointLL(p1,p2,p3,p4);
    }
    
    bool intersectShL(P p1,P p2,P vec){
        vec/=abs(vec);
        return intersectSL(p1,p2,vec) &&
        crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;
    }
    
    bool intersectShL(P p1,P p2,P p3,P p4){
        return intersectShL(p1-p3,p2-p3,p4-p3);
    }
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        int s=A.size();
        vector<bool> cnt(s,false);
        for(int i=0;i<(int)poly.size();i++){
            int k=(i+1)%poly.size();
            if(distSP(poly[i],poly[k],p)<EPS){return 0;}
            for(int j=0;j<s;j++){
                if(intersectShL(poly[i],poly[k],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<s;j++){if(cnt[j]){in++;}}
        return in>s/2?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=0;i<(int)poly.size();i++){
            int j=(i+1)%poly.size();
            if(cross(p2-p1,poly[i]-p1)>-EPS){ret.push_back(poly[i]);}
            if(intersectSL(poly[i],poly[j],p1,p2) &&
               distLP(p1,p2,poly[i])>EPS && distLP(p1,p2,poly[j])>EPS){
                ret.push_back(crosspointLL(poly[i],poly[j],p1,p2));
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<(int)poly.size();i++){
            ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);
        }
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        auto fnc=[&](){
            for(auto &I:pts){
                if(!ret.empty() && I==ret.back()){continue;}
                while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){
                    ret.pop_back();
                }
                ret.push_back(I);
            }
        };
        fnc();
        reverse(pts.begin(),pts.end());
        fnc();
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){
            if(distSP(p1,p2,I)<EPS){ret.push_back(I);}
        }
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){
        return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));
    }
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<(int)poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        int N=pt.size();
        for(int i=1;i<N;i<<=1){
            for(int j=0;i+j<N;j+=i*2){
                int m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(int k=j;k<m;k++){l=max(l,pt[k].real());}
                for(int k=0;m+k<N && k<i;k++){r=min(r,pt[m+k].real());}
                for(int k=0;m+k<N && k<i;k++){
                    if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}
                }
                int idx=0;
                for(int k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    int M=R.size();
                    while(idx<M && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(int s=idx;s<M && R[s].imag()-pt[k].imag()<ret;s++){
                        ret=min(ret,abs(R[s]-pt[k]));
                    }
                }
                auto ed=(j+i*2<N?pt.begin()+j+2*i:pt.end());
                inplace_merge(pt.begin()+j,pt.begin()+m,ed,comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<(int)pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=(int)L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto less=[](P a,P b){return abs(a-b)<EPS?false:comp(a,b);};
        sort(pt.begin(),pt.end(),less);
        pt.erase(unique(pt.begin(),pt.end(),[](P a,P b){return abs(a-b)<EPS;}),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || abs(pt[v]-pt[pre])<EPS?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};

using namespace Geometry;



int main(){
    cout<<fixed<<setprecision(15);
    ll N,M;
    cin>>N>>M;
    vector<pair<P,P>> A(N);
    cin>>A;
    vector<P> B(M);
    cin>>B;
    P s,t;
    cin>>s>>t;
    vector<P> pt=B;
    pt.push_back(s);
    pt.push_back(t);
    vector<pair<int,int>> seg;
    segment_arrangement(A,seg,pt);
    vector<vector<int>> edge(pt.size());
    for(auto &I:seg){
        edge[I.F].push_back(I.S);
        edge[I.S].push_back(I.F);
    }
    vector<bool> used(pt.size(),false);
    vector<bool> closed(pt.size(),false);
    vector<bool> bulb(pt.size(),false);
    for(auto &I:B){
        for(int j=0;j<pt.size();j++){
            if(abs(I-pt[j])<EPS){bulb[j]=true;}
        }
    }
    function<void(int)> dfs=[&](int v){
        if(bulb[v]){closed[v]=true; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-t)<EPS){dfs(i);}
    }
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS && used[i]){
            cout<<-1<<endl;
            return 0;
        }
    }
    for(int i=0;i<pt.size();i++){used[i]=false;}
    function<void(int)> dfs2=[&](int v){
        if(closed[v]){used[v]=false; return;}
        for(auto &u:edge[v]){
            if(!used[u]){
                used[u]=true;
                dfs2(u);
            }
        }
    };
    for(int i=0;i<pt.size();i++){
        if(abs(pt[i]-s)<EPS){used[i]=true; dfs2(i);}
    }
    D sum=0;
    for(auto &I:seg){
        if(!used[I.F] && !used[I.S]){sum+=abs(pt[I.F]-pt[I.S]);}
    }
    cout<<sum<<endl;
    
    
    return 0;
}
accuracy: 1
time_ms: 860
memory_kb: 4984
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
//BEGIN CUT HERE

#define EPS (1e-10)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define PI 3.141592653589793238
 
// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

//Intercsect Circle & Circle
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

struct Point{
  double x,y;
  Point(){}
  Point(double x,double y) :x(x),y(y){}
  Point operator+(Point p) {return Point(x+p.x,y+p.y);}
  Point operator-(Point p) {return Point(x-p.x,y-p.y);}
  Point operator*(double k){return Point(x*k,y*k);}
  Point operator/(double k){return Point(x/k,y/k);}
  double norm(){return x*x+y*y;}
  double abs(){return sqrt(norm());}

  bool operator < (const Point &p) const{
    return x!=p.x?x<p.x:y<p.y;
    //grid-point only
    //return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
  }

  bool operator == (const Point &p) const{
    return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
  }
};

struct EndPoint{
  Point p;
  int seg,st;
  EndPoint(){}
  EndPoint(Point p,int seg,int st):p(p),seg(seg),st(st){}
  bool operator<(const EndPoint &ep)const{
    if(p.y==ep.p.y) return st<ep.st;
    return p.y<ep.p.y;
  }
};

istream &operator >> (istream &is,Point &p){
  is>>p.x>>p.y;
  return is;
}

ostream &operator << (ostream &os,Point p){
  os<<fixed<<setprecision(12)<<p.x<<" "<<p.y;
  return os;
}

bool sort_x(Point a,Point b){
  return a.x!=b.x?a.x<b.x:a.y<b.y;
}

bool sort_y(Point a,Point b){
  return a.y!=b.y?a.y<b.y:a.x<b.x;
}

typedef Point Vector;
typedef vector<Point> Polygon;

istream &operator >> (istream &is,Polygon &p){
  for(int i=0;i<(int)p.size();i++) is>>p[i];
  return is;
}

struct Segment{
  Point p1,p2;
  Segment(){}
  Segment(Point p1, Point p2):p1(p1),p2(p2){}
};
typedef Segment Line;

istream &operator >> (istream &is,Segment &s){
  is>>s.p1>>s.p2;
  return is;
}

struct Circle{
  Point c;
  double r;
  Circle(){}
  Circle(Point c,double r):c(c),r(r){}
};

istream &operator >> (istream &is,Circle &c){
  is>>c.c>>c.r;
  return is;
}

double norm(Vector a){
  return a.x*a.x+a.y*a.y;
}
double abs(Vector a){
  return sqrt(norm(a));
}
double dot(Vector a,Vector b){
  return a.x*b.x+a.y*b.y;
}
double cross(Vector a,Vector b){
  return a.x*b.y-a.y*b.x;
}

Point orth(Point p){return Point(-p.y,p.x);}

bool isOrthogonal(Vector a,Vector b){
  return equals(dot(a,b),0.0);
}

bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
  return isOrthogonal(a1-a2,b1-b2);
}

bool isOrthogonal(Segment s1,Segment s2){
  return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Point a1,Point a2,Point b1,Point b2){
  return isParallel(a1-a2,b1-b2);
}

bool isParallel(Segment s1,Segment s2){
  return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0); 
}

Point project(Segment s,Point p){
  Vector base=s.p2-s.p1;
  double r=dot(p-s.p1,base)/norm(base);
  return s.p1+base*r;
}

Point reflect(Segment s,Point p){
  return p+(project(s,p)-p)*2.0;
}

double arg(Vector p){
  return atan2(p.y,p.x);
}

Vector polar(double a,double r){
  return Point(cos(r)*a,sin(r)*a);
}

int ccw(Point p0,Point p1,Point p2);
bool intersectSS(Point p1,Point p2,Point p3,Point p4);
bool intersectSS(Segment s1,Segment s2);
bool intersectPS(Polygon p,Segment l);
int intersectCC(Circle c1,Circle c2);
bool intersectSC(Segment s,Circle c);
double getDistanceLP(Line l,Point p);
double getDistanceSP(Segment s,Point p);
double getDistanceSS(Segment s1,Segment s2);
Point getCrossPointSS(Segment s1,Segment s2);
Point getCrossPointLL(Line l1,Line l2);
Polygon getCrossPointCL(Circle c,Line l);
Polygon getCrossPointCC(Circle c1,Circle c2);
int contains(Polygon g,Point p);
Polygon andrewScan(Polygon s);
Polygon convex_hull(Polygon ps);
double diameter(Polygon s);
bool isConvex(Polygon p);
double area(Polygon s);
Polygon convexCut(Polygon p,Line l);
Line bisector(Point p1,Point p2);
Vector translate(Vector v,double theta);
vector<Line> corner(Line l1,Line l2);
vector< vector<int> >
segmentArrangement(vector<Segment> &ss, Polygon &ps);
  
int ccw(Point p0,Point p1,Point p2){
  Vector a = p1-p0;
  Vector b = p2-p0;
  if(cross(a,b) > EPS) return CCW_COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS) return CCW_CLOCKWISE;
  if(dot(a,b) < -EPS) return CCW_ONLINE_BACK;
  if(a.norm()<b.norm()) return CCW_ONLINE_FRONT;
  return CCW_ON_SEGMENT;
}

bool intersectSS(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4) <= 0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2) <= 0 );
}

bool intersectSS(Segment s1,Segment s2){
  return intersectSS(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool intersectPS(Polygon p,Segment l){
  int n=p.size();
  for(int i=0;i<n;i++)
    if(intersectSS(Segment(p[i],p[(i+1)%n]),l)) return 1;
  return 0;
}

int intersectCC(Circle c1,Circle c2){
  if(c1.r<c2.r) swap(c1,c2);
  double d=abs(c1.c-c2.c);
  double r=c1.r+c2.r;
  if(equals(d,r)) return ICC_CIRCUMSCRIBE;
  if(d>r) return ICC_SEPERATE;
  if(equals(d+c2.r,c1.r)) return ICC_INSCRIBE;
  if(d+c2.r<c1.r) return ICC_CONTAIN;
  return ICC_INTERSECT;
}

bool intersectSC(Segment s,Circle c){
  return getDistanceSP(s,c.c)<=c.r;
}

int intersectCS(Circle c,Segment s){
  if(norm(project(s,c.c)-c.c)-c.r*c.r>EPS) return 0;
  double d1=abs(c.c-s.p1),d2=abs(c.c-s.p2);
  if(d1<c.r+EPS&&d2<c.r+EPS) return 0;
  if((d1<c.r-EPS&&d2>c.r+EPS)||(d1>c.r+EPS&&d2<c.r-EPS)) return 1;
  Point h=project(s,c.c);
  if(dot(s.p1-h,s.p2-h)<0) return 2;
  return 0;
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
  if(dot(s.p2-s.p1,p-s.p1) < 0.0 ) return abs(p-s.p1);
  if(dot(s.p1-s.p2,p-s.p2) < 0.0 ) return abs(p-s.p2);
  return getDistanceLP(s,p);
}

double getDistanceSS(Segment s1,Segment s2){
  if(intersectSS(s1,s2)) return 0.0;
  return min(min(getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2)),
             min(getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)));
}

Point getCrossPointSS(Segment s1,Segment s2){
  for(int k=0;k<2;k++){
    if(getDistanceSP(s1,s2.p1)<EPS) return s2.p1; 
    if(getDistanceSP(s1,s2.p2)<EPS) return s2.p2;
    swap(s1,s2);
  }
  Vector base=s2.p2-s2.p1;
  double d1=abs(cross(base,s1.p1-s2.p1));
  double d2=abs(cross(base,s1.p2-s2.p1));
  double t=d1/(d1+d2);
  return s1.p1+(s1.p2-s1.p1)*t;
}

Point getCrossPointLL(Line l1,Line l2){
  double a=cross(l1.p2-l1.p1,l2.p2-l2.p1);
  double b=cross(l1.p2-l1.p1,l1.p2-l2.p1);
  if(abs(a)<EPS&&abs(b)<EPS) return l2.p1;
  return l2.p1+(l2.p2-l2.p1)*(b/a);
}

Polygon getCrossPointCL(Circle c,Line l){
  Polygon ps;
  Point pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  if(equals(getDistanceLP(l,c.c),c.r)){
    ps.emplace_back(pr);
    return ps;
  }
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  ps.emplace_back(pr+e*base);
  ps.emplace_back(pr-e*base);
  return ps;
}

Polygon getCrossPointCS(Circle c,Segment s){
  Line l(s);
  Polygon res=getCrossPointCL(c,l);
  if(intersectCS(c,s)==2) return res;
  if(res.size()>1u){
    if(dot(l.p1-res[0],l.p2-res[0])>0) swap(res[0],res[1]);
    res.pop_back();
  }
  return res;
}


Polygon getCrossPointCC(Circle c1,Circle c2){
  Polygon p(2);
  double d=abs(c1.c-c2.c);
  double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
  double t=arg(c2.c-c1.c);
  p[0]=c1.c+polar(c1.r,t+a);
  p[1]=c1.c+polar(c1.r,t-a);
  return p;
}

// IN:2 ON:1 OUT:0
int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Point a=g[i]-p,b=g[(i+1)%n]-p;
    if(fabs(cross(a,b)) < EPS && dot(a,b) < EPS) return 1;
    if(a.y>b.y) swap(a,b);
    if(a.y < EPS && EPS < b.y && cross(a,b) > EPS ) x = !x;
  }
  return (x?2:0);
}

Polygon andrewScan(Polygon s){
  Polygon u,l;
  if(s.size()<3) return s;
  sort(s.begin(),s.end());
  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);
  for(int i=2;i<(int)s.size();i++){
    for(int n=u.size();n>=2&&ccw(u[n-2],u[n-1],s[i])!=CCW_CLOCKWISE;n--){
      u.pop_back();
    }
    u.push_back(s[i]);
  } 
  for(int i=s.size()-3;i>=0;i--){
    for(int n=l.size();n>=2&&ccw(l[n-2],l[n-1],s[i])!=CCW_CLOCKWISE;n--){
      l.pop_back();
    }
    l.push_back(s[i]);
  }
  reverse(l.begin(),l.end());
  for(int i=u.size()-2;i>=1;i--) l.push_back(u[i]);
  return l;
} 

Polygon convex_hull(Polygon ps){
  int n=ps.size();
  sort(ps.begin(),ps.end(),sort_y);
  int k=0;
  Polygon qs(n*2);
  for(int i=0;i<n;i++){
    while(k>1&&cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0) k--;
    qs[k++]=ps[i];
  }
  for(int i=n-2,t=k;i>=0;i--){
    while(k>t&&cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0) k--;
    qs[k++]=ps[i];
  }
  qs.resize(k-1);
  return qs;
}

double diameter(Polygon s){
  Polygon p=s;
  int n=p.size();
  if(n==2) return abs(p[0]-p[1]);
  int i=0,j=0;
  for(int k=0;k<n;k++){
    if(p[i]<p[k]) i=k;
    if(!(p[j]<p[k])) j=k;
  }
  double res=0;
  int si=i,sj=j;
  while(i!=sj||j!=si){
    res=max(res,abs(p[i]-p[j]));
    if(cross(p[(i+1)%n]-p[i],p[(j+1)%n]-p[j])<0.0){
      i=(i+1)%n;
    }else{
      j=(j+1)%n;
    }
  }
  return res;
}

bool isConvex(Polygon p){
  bool f=1;
  int n=p.size();
  for(int i=0;i<n;i++){
    int t=ccw(p[(i+n-1)%n],p[i],p[(i+1)%n]);
    f&=t!=CCW_CLOCKWISE;
  }
  return f;
}

double area(Polygon s){
  double res=0;
  for(int i=0;i<(int)s.size();i++){
    res+=cross(s[i],s[(i+1)%s.size()])/2.0;
  }
  return res;
}

double area(Circle c1,Circle c2){
  double d=abs(c1.c-c2.c);
  if(c1.r+c2.r<=d+EPS) return 0;
  if(d<=abs(c1.r-c2.r)){
    double r=min(c1.r,c2.r);
    return PI*r*r;
  }
  double rc=(d*d+c1.r*c1.r-c2.r*c2.r)/(2*d);
  double th=acos(rc/c1.r);
  double ph=acos((d-rc)/c2.r);
  return c1.r*c1.r*th+c2.r*c2.r*ph-d*c1.r*sin(th);
}

Polygon convexCut(Polygon p,Line l){
  Polygon q;
  for(int i=0;i<(int)p.size();i++){
    Point a=p[i],b=p[(i+1)%p.size()];
    if(ccw(l.p1,l.p2,a)!=-1) q.push_back(a);
    if(ccw(l.p1,l.p2,a)*ccw(l.p1,l.p2,b)<0)
      q.push_back(getCrossPointLL(Line(a,b),l));
  }
  return q;
}

Line bisector(Point p1,Point p2){
  Circle c1=Circle(p1,abs(p1-p2)),c2=Circle(p2,abs(p1-p2));
  Polygon p=getCrossPointCC(c1,c2);
  if(cross(p2-p1,p[0]-p1)>0) swap(p[0],p[1]);
  return Line(p[0],p[1]);
}

Vector translate(Vector v,double theta){
  Vector res;
  res.x=cos(theta)*v.x-sin(theta)*v.y;
  res.y=sin(theta)*v.x+cos(theta)*v.y;
  return res;
}

vector<Line> corner(Line l1,Line l2){
  vector<Line> res;
  if(isParallel(l1,l2)){
    double d=getDistanceLP(l1,l2.p1)/2.0;
    Vector v1=l1.p2-l1.p1;
    v1=v1/v1.abs()*d;
    Point p=l2.p1+translate(v1,90.0*(PI/180.0));
    double d1=getDistanceLP(l1,p);
    double d2=getDistanceLP(l2,p);
    if(abs(d1-d2)>d){
      p=l2.p1+translate(v1,-90.0*(PI/180.0));
    }
    res.push_back(Line(p,p+v1));
  }else{
    Point p=getCrossPointLL(l1,l2);
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    v1=v1/v1.abs();
    v2=v2/v2.abs();
    res.push_back(Line(p,p+(v1+v2)));
    res.push_back(Line(p,p+translate(v1+v2,90.0*(PI/180.0))));
  }
  return res;
}

Polygon tangent(Circle c1,Point p2){
  Circle c2=Circle(p2,sqrt(norm(c1.c-p2)-c1.r*c1.r));
  Polygon p=getCrossPointCC(c1,c2);
  sort(p.begin(),p.end());
  return p;
}

vector<Line> tangent(Circle c1,Circle c2){
  vector<Line> ls;
  if(c1.r<c2.r) swap(c1,c2);
  double g=norm(c1.c-c2.c);
  if(equals(g,0)) return ls;
  Point u=(c2.c-c1.c)/sqrt(g);
  Point v=orth(u);
  for(int s=1;s>=-1;s-=2){
    double h=(c1.r+s*c2.r)/sqrt(g);
    if(equals(1-h*h,0)){
      ls.emplace_back(c1.c+u*c1.r,c1.c+(u+v)*c1.r);
    }else if(1-h*h>0){
      Point uu=u*h,vv=v*sqrt(1-h*h);
      ls.emplace_back(c1.c+(uu+vv)*c1.r,c2.c-(uu+vv)*c2.r*s);
      ls.emplace_back(c1.c+(uu-vv)*c1.r,c2.c-(uu-vv)*c2.r*s);
    }
  }
  
  return ls;
}

double closest_pair(Polygon &a,int l=0,int r=-1){
  if(r<0){
    r=a.size();
    sort(a.begin(),a.end(),sort_x);
  }
  if(r-l<=1) return abs(a[0]-a[1]);
  int m=(l+r)>>1;
  double x=a[m].x;
  double d=min(closest_pair(a,l,m),closest_pair(a,m,r));
  inplace_merge(a.begin()+l,a.begin()+m,a.begin()+r,sort_y);

  Polygon b;
  for(int i=l;i<r;i++){
    if(fabs(a[i].x-x)>=d) continue;
    for(int j=0;j<(int)b.size();j++){
      double dy=a[i].y-next(b.rbegin(),j)->y;
      if(dy>=d) break;
      d=min(d,abs(a[i]-*next(b.rbegin(),j)));
    }
    b.emplace_back(a[i]);
  }
  return d;
}

vector<vector<int> > 
segmentArrangement(vector<Segment> &ss, Polygon &ps){
  int n=ss.size();
  for(int i=0;i<n;i++){
    ps.emplace_back(ss[i].p1);
    ps.emplace_back(ss[i].p2);
    for(int j=i+1;j<n;j++)
      if(intersectSS(ss[i],ss[j]))
        ps.emplace_back(getCrossPointSS(ss[i],ss[j]));
  }
  sort(ps.begin(),ps.end());
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<int> > G(ps.size());
  for(int i=0;i<n;i++){
    vector<pair<double,int> > ls;
    for(int j=0;j<(int)ps.size();j++)
      if(getDistanceSP(ss[i],ps[j])<EPS)
        ls.emplace_back(make_pair(norm(ss[i].p1-ps[j]),j));
      
    sort(ls.begin(),ls.end());
    for(int j=0;j+1<(int)ls.size();j++){
      int a=ls[j].second,b=ls[j+1].second;
      G[a].emplace_back(b);
      G[b].emplace_back(a);
    }
  }  
  for(auto &v:G){
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());    
  }
  return G;
}

int manhattanIntersection(vector<Segment> ss,const int INF){
  const int BTM = 0;
  const int LFT = 1;
  const int RGH = 2;
  const int TOP = 3;
  
  int n=ss.size();
  vector<EndPoint> ep;
  for(int i=0;i<n;i++){
    if(ss[i].p1.y==ss[i].p2.y){
      if(ss[i].p1.x>ss[i].p2.x) swap(ss[i].p1,ss[i].p2);
      ep.emplace_back(ss[i].p1,i,LFT);
      ep.emplace_back(ss[i].p2,i,RGH);
    }else{
      if(ss[i].p1.y>ss[i].p2.y) swap(ss[i].p1,ss[i].p2);      
      ep.emplace_back(ss[i].p1,i,BTM);
      ep.emplace_back(ss[i].p2,i,TOP);
    }    
  }   
  sort(ep.begin(),ep.end());

  set<int> bt;
  bt.insert(INF);
  
  int cnt=0;
  for(int i=0;i<n*2;i++){
    if(ep[i].st==TOP){
      bt.erase(ep[i].p.x);
    }else if(ep[i].st==BTM){
      bt.emplace(ep[i].p.x);
    }else if(ep[i].st==LFT){
      auto b=bt.lower_bound(ss[ep[i].seg].p1.x);
      auto e=bt.upper_bound(ss[ep[i].seg].p2.x);
      cnt+=distance(b,e);
    }    
  }
  
  return cnt;
}

double area(Polygon ps,Circle c){
  if(ps.size()<3u) return 0;
  function<double(Circle, Point, Point)> dfs=
    [&](Circle c,Point a,Point b){
      Vector va=c.c-a,vb=c.c-b;
      double f=cross(va,vb),res=0;
      if(equals(f,0.0)) return res;
      if(max(abs(va),abs(vb))<c.r+EPS) return f;
      Vector d(dot(va,vb),cross(va,vb));
      if(getDistanceSP(Segment(a,b),c.c)>c.r-EPS)
        return c.r*c.r*atan2(d.y,d.x);
      auto u=getCrossPointCS(c,Segment(a,b));
      if(u.empty()) return res;
      if(u.size()>1u&&dot(u[1]-u[0],a-u[0])>0) swap(u[0],u[1]);
      u.emplace(u.begin(),a);
      u.emplace_back(b);
      for(int i=1;i<(int)u.size();i++)
        res+=dfs(c,u[i-1],u[i]);
      return res;
    };
  double res=0;
  for(int i=0;i<(int)ps.size();i++)
    res+=dfs(c,ps[i],ps[(i+1)%ps.size()]);
  return res/2;
}

//END CUT HERE

//Projection
signed AOJ_CGL1A(){
  Point p1,p2;
  cin>>p1>>p2;
  int q;
  cin>>q;
  while(q--){
    Point p;
    cin>>p;
    cout<<project(Line(p1,p2),p)<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A&lang=jp
*/

//Reflect
signed AOJ_CGL1B(){
  Point p1,p2;
  cin>>p1>>p2;
  int q;
  cin>>q;
  while(q--){
    Point p;
    cin>>p;
    cout<<reflect(Line(p1,p2),p)<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B&lang=jp
*/

//CCW
signed AOJ_CGL1C(){
  Point p0,p1;
  cin>>p0>>p1;
  int q;
  cin>>q;
  while(q--){
    Point p2;
    cin>>p2;
    int t=ccw(p0,p1,p2);
    if(t==CCW_COUNTER_CLOCKWISE) cout<<"COUNTER_CLOCKWISE"<<endl;
    if(t==CCW_CLOCKWISE) cout<<"CLOCKWISE"<<endl;
    if(t==CCW_ONLINE_BACK) cout<<"ONLINE_BACK"<<endl;
    if(t==CCW_ONLINE_FRONT) cout<<"ONLINE_FRONT"<<endl;
    if(t==CCW_ON_SEGMENT) cout<<"ON_SEGMENT"<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C&lang=jp
*/

//Parallel / Orthogonal
signed AOJ_CGL2A(){
  int q;
  cin>>q;
  while(q--){
    Point p0,p1,p2,p3;
    cin>>p0>>p1>>p2>>p3;
    if(isParallel(Line(p0,p1),Line(p2,p3))) cout<<2<<endl;
    else if(isOrthogonal(Line(p0,p1),Line(p2,p3))) cout<<1<<endl;
    else cout<<0<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A&lang=jp
*/

//intersectSS
signed AOJ_CGL2B(){
  int q;
  cin>>q;
  while(q--){
    Point p0,p1,p2,p3;
    cin>>p0>>p1>>p2>>p3;
    cout<<(intersectSS(Segment(p0,p1),Segment(p2,p3)))<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B&lang=jp
*/

//cross point
signed AOJ_CGL2C(){
  int q;
  cin>>q;
  while(q--){
    Point p0,p1,p2,p3;
    cin>>p0>>p1>>p2>>p3;
    cout<<getCrossPointSS(Segment(p0,p1),Segment(p2,p3))<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C&lang=jp
*/

//distanceSS
signed AOJ_CGL2D(){
  int q;
  cin>>q;
  while(q--){
    Point p0,p1,p2,p3;
    cin>>p0>>p1>>p2>>p3;
    printf("%.12f\n",getDistanceSS(Segment(p0,p1),Segment(p2,p3)));
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D&lang=jp
*/

//area of Polygon
signed AOJ_CGL3A(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  printf("%.1f\n",area(p));
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A&lang=jp
*/


//isConvex
signed AOJ_CGL3B(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  cout<<isConvex(p)<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B&lang=jp
*/



//contains
signed AOJ_CGL3C(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  int q;
  cin>>q;
  while(q--){
    Point r;
    cin>>r;
    cout<<contains(p,r)<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
*/


//convex hull
signed AOJ_CGL4A(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  Polygon q=convex_hull(p);
  cout<<q.size()<<endl;
  for(Point v:q) cout<<v.x<<" "<<v.y<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A&lang=jp
*/

//diameter of Polygon
signed AOJ_CGL4B(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  printf("%.12f\n",diameter(p));
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_B&lang=jp
*/

//convexCut:
signed AOJ_CGL4C(){
  int n;
  cin>>n;
  Polygon g(n);
  for(int i=0;i<n;i++) cin>>g[i];
  Polygon p=andrewScan(g);
  int q;
  cin>>q;
  while(q--){
    Line l;
    cin>>l.p1>>l.p2;
    printf("%.12f\n",area(convexCut(p,l)));
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C&lang=jp
*/

//closest pair:
signed AOJ_CGL5A(){
  int n;
  cin>>n;
  Polygon p(n);
  for(int i=0;i<n;i++) cin>>p[i];
  cout<<fixed<<setprecision(12)<<closest_pair(p)<<endl;
  return 0;
}
/*
  verified on 2018/01/04
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_5_A&lang=jp
*/

//manhattanIntersection:
signed AOJ_CGL6A(){
  int n;
  cin>>n;
  vector<Segment> ss(n);
  for(int i=0;i<n;i++) cin>>ss[i];
  //for(int i=0;i<n;i++) cout<<ss[i].p1<<":"<<ss[i].p2<<endl;
  cout<<manhattanIntersection(ss,1e9+10)<<endl;
  return 0;
}
/*
  verified on 2018/06/18
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_6_A&lang=jp
*/

//intersectCC
signed AOJ_CGL7A(){
  Circle c1,c2;
  cin>>c1>>c2;
  cout<<intersectCC(c1,c2)<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
*/


//getCrossPointCL
signed AOJ_CGL7D(){
  Circle c;
  int q;
  cin>>c>>q;
  while(q--){
    Line l;
    cin>>l;
    auto pp=getCrossPointCL(c,l);
    if(pp.size()==1u) pp.emplace_back(pp[0]);
    if(pp[1]<pp[0]) swap(pp[0],pp[1]);
    cout<<pp[0]<<" "<<pp[1]<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D&lang=jp
*/

//intersectCC
signed AOJ_CGL7E(){
  Circle c1,c2;
  cin>>c1>>c2;
  auto pp=getCrossPointCC(c1,c2);
  if(pp.size()==1u) pp.emplace_back(pp[0]);
  if(pp[1]<pp[0]) swap(pp[0],pp[1]);
  cout<<pp[0]<<" "<<pp[1]<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E&lang=jp
*/

//tangent to a Circle
signed AOJ_CGL7F(){
  Point p;
  Circle c;
  cin>>p>>c;
  auto pp=tangent(c,p);
  for(auto p:pp) cout<<p<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F&lang=jp
*/

//Common Tangent
signed AOJ_CGL7G(){
  Circle c1,c2;
  cin>>c1>>c2;
  auto ls=tangent(c1,c2);
  Polygon ps;
  for(auto l:ls) ps.emplace_back(getCrossPointCL(c1,l)[0]);
  sort(ps.begin(),ps.end());
  for(auto p:ps) cout<<p<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge//description.jsp?id=CGL_7_G&lang=jp
*/

//Intersection of a Circle and a Polygon
signed AOJ_CGL7H(){
  int n;
  double r;
  cin>>n>>r;
  Circle c(Point(0,0),r);
  Polygon ps(n);
  for(int i=0;i<n;i++) cin>>ps[i];
  cout<<fixed<<setprecision(12)<<area(ps,c)<<endl;
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge//description.jsp?id=CGL_7_G&lang=jp
*/

//area of 2 circles' intersection
signed AOJ_2572(){
  double uw,uh,a,b,ab;
  while(cin>>uw>>uh>>a>>b>>ab,uw!=0){
    Circle c1(Point(0,0),sqrt(a/PI));
    Circle c2(Point(0,0),sqrt(b/PI));
    bool f=0;
    if(c1.r<=c2.r) swap(c1,c2),f=1;
    double l=max(0.0,c1.r-c2.r),r=c1.r+c2.r+EPS;
    for(int k=0;k<100;k++){
      double m=(l+r)/2;
      c2.c.x=m;
      //cout<<area(c1,c2)<<endl;
      if(area(c1,c2)<=ab) r=m;
      else l=m;
    }
    c2.c.x=l;
    
    double EPS3=1e-4;
    assert(abs(area(c1,c2)-ab)<=EPS3);

    l=0,r=PI/2;
    for(int k=0;k<200;k++){
      double m=(l+r)/2;
      Circle t=c2;
      t.c=translate(c2.c,m);
      if(c1.r+max(c1.r,t.c.x+t.r)<=uw) r=m;
      else l=m;
    }
    c2.c=translate(c2.c,r);
    //cout<<c1.c<<"/"<<c2.c<<endl;
    
    Vector v(c1.r,c1.r);
    c1.c=c1.c+v;
    c2.c=c2.c+v;
    
    //cout<<c1.c<<"/"<<c2.c<<endl;

    if(f) swap(c1,c2);
    f=1;
    f&=(c1.c.x-c1.r>=-EPS3);
    f&=(c1.c.x+c1.r<=uw+EPS3);
    f&=(c1.c.y-c1.r>=-EPS3);
    f&=(c1.c.y+c1.r<=uh+EPS3);
    f&=(c2.c.x-c2.r>=-EPS3);
    f&=(c2.c.x+c2.r<=uw+EPS3);
    f&=(c2.c.y-c2.r>=-EPS3);
    f&=(c2.c.y+c2.r<=uh+EPS3);
    if(f) cout<<c1.c<<" "<<c1.r<<" "<<c2.c<<" "<<c2.r<<endl;
    else cout<<"impossible"<<endl;
    //else cout<<c1.c<<" "<<c1.r<<"/"<<c2.c<<" "<<c2.r<<endl;
  }
  return 0;
}
/*
  verified on 2017/12/31
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2572
*/

//Segment Arrangement
signed AOJ_2454(){
  int n,m;
  cin>>n>>m;
  vector<Segment> ss(n);
  Polygon ps(m);
  for(int i=0;i<n;i++) cin>>ss[i];
  for(int i=0;i<m;i++) cin>>ps[i];
  map<Point, int> mp;
  for(int i=0;i<m;i++) mp[ps[i]]=i;
  Point s,g;
  cin>>s>>g;
  ps.emplace_back(s);
  ps.emplace_back(g);

  auto H=segmentArrangement(ss,ps);
  vector<vector<pair<int, double> > > G(H.size());
  for(int i=0;i<(int)H.size();i++)
    for(int j:H[i]) G[i].emplace_back(j,abs(ps[i]-ps[j]));
  
  double ans=0,tmp=0;
  for(int i=0;i<n;i++) ans+=abs(ss[i].p1-ss[i].p2);

  vector<int> used(G.size(),0);
  queue<int> q;
  for(int i=0;i<(int)G.size();i++)
    if(ps[i]==g) {used[i]=1;q.emplace(i);}

  while(!q.empty()){
    int v=q.front();q.pop();
    if(ps[v]==s){
      cout<<(int)-1<<endl;
      return 0;
    }
    if(mp.count(ps[v])) continue;
    for(int u:H[v]){
      if(!used[u]){
        used[u]=1;
        q.emplace(u);
      }
    }
  }
  
  for(int i=0;i<(int)G.size();i++)
    if(ps[i]==s) q.emplace(i);

  while(!q.empty()){
    int v=q.front();q.pop();
    for(auto &e:G[v]){
      int u=e.first;
      double &c=e.second;
      if(used[v]&&used[u]) continue;
      if(c==0) continue;
      tmp+=c;c=0;
      q.emplace(u);
    }
  }
  tmp/=2;
  
  cout<<fixed<<setprecision(12)<<ans-tmp<<endl;
  return 0;
}
/*
  verified on 2018/01/27
  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2454
*/



signed main(){
  //AOJ_CGL1A();
  //AOJ_CGL1B();
  //AOJ_CGL1C();

  //AOJ_CGL2A();
  //AOJ_CGL2B();
  //AOJ_CGL2C();
  //AOJ_CGL2D();
  
  //AOJ_CGL3A();
  //AOJ_CGL3B();
  //AOJ_CGL3C();
  
  //AOJ_CGL4A();
  //AOJ_CGL4B();
  //AOJ_CGL4C();
  
  //AOJ_CGL5A();

  //AOJ_CGL6A();
  
  //AOJ_CGL7A();
  //AOJ_CGL7D();
  //AOJ_CGL7E();
  //AOJ_CGL7F();
  //AOJ_CGL7G();
  //AOJ_CGL7H();

  //AOJ_2572();
  AOJ_2454();
  
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5360
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define bcnt __builtin_popcountll

typedef long double D;
typedef complex<D> P;

#define X real()
#define Y imag()

const D eps=1e-12;
const D inf=1e12;
const D PI=acos(-1);

bool cmp_x(const P& a,const P& b){ return a.X==b.X?a.Y<b.Y:a.X<b.X; }
bool cmp_y(const P& a,const P& b){ return a.Y==b.Y?a.X<b.X:a.Y<b.Y; }
bool cmp_a(const P& a,const P& b){ return arg(a)==arg(b)?norm(a)<norm(b):arg(a)<arg(b); }
D cross(P a,P b){ return (conj(a)*b).Y; }
D dot(P a,P b){ return (conj(a)*b).X; }
D toRag(D deg){ return deg*PI/180.0; }
P rot(P base,P a,D theta){ return base+polar(abs(a-base),arg(a-base)+theta); }
struct L : public vector<P> { // line and segment
  L(const P& a,const P &b){
    push_back(a);
    push_back(b);
  }
};
P crosspoint(L l,L m) {
  D A=cross(l[1]-l[0],m[1]-m[0]);
  D B=cross(l[1]-l[0],l[1]-m[0]);
  if (abs(A)<eps&&abs(B)<eps) return m[0]; // same line
  if (abs(A)<eps) return P(-100000,-100000);
  return m[0]+B/A*(m[1]-m[0]);
}
bool intersectSP(L s,P p){
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0])<eps;
}

int N,M;
P sp,tp;
vector<L> ls;
vector<P> ps;
struct edge{
  int u,v;
  D cost;
};
vector<int> g[100010];
vector<edge> es;
bool vis[2][100010];

bool exist(P p){
  rep(i,ps.size())if(abs(p-ps[i])<eps)return true;
  return false;
}

int main(){
  cin>>N>>M;
  rep(i,N){
    int x0,y0,x1,y1;
    cin>>x0>>y0>>x1>>y1;
    ls.push_back(L(P(x0,y0),P(x1,y1)));
  }
  rep(i,M){
    int x,y;
    cin>>x>>y;
    ps.push_back(P(x,y));
  }
  {
    int x,y;
    cin>>x>>y;
    sp=P(x,y);
    cin>>x>>y;
    tp=P(x,y);
  }

  ps.push_back(sp); ps.push_back(tp);

  rep(i,N){
    if(!exist(ls[i][0]))ps.push_back(ls[i][0]);
    if(!exist(ls[i][1]))ps.push_back(ls[i][1]);
    rep(j,i){
      P cp=crosspoint(ls[i],ls[j]);
      if(cp==P(-100000,-100000))continue;
      D x0=max(min(ls[i][0].X,ls[i][1].X),min(ls[j][0].X,ls[j][1].X));
      D x1=min(max(ls[i][0].X,ls[i][1].X),max(ls[j][0].X,ls[j][1].X));
      D y0=max(min(ls[i][0].Y,ls[i][1].Y),min(ls[j][0].Y,ls[j][1].Y));
      D y1=min(max(ls[i][0].Y,ls[i][1].Y),max(ls[j][0].Y,ls[j][1].Y));
      if(cp.X<x0||cp.X>x1||cp.Y<y0||cp.Y>y1)continue;
      if(!exist(cp))ps.push_back(cp);
    }
  }

  D sum=0;
  rep(i,N){
    vector<int> idxs;
    rep(j,ps.size()){
      if(intersectSP(ls[i],ps[j]))idxs.push_back(j);
    }
    sort(all(idxs),[=](const int& a,const int& b){ return cmp_x(ps[a],ps[b]); });
    rep(j,idxs.size()-1){
      es.push_back((edge){idxs[j],idxs[j+1],abs(ps[idxs[j]]-ps[idxs[j+1]])});
      sum+=abs(ps[idxs[j]]-ps[idxs[j+1]]);
      g[idxs[j]].push_back(idxs[j+1]);
      g[idxs[j+1]].push_back(idxs[j]);
    }
  }

  {
    queue<int> que;
    que.push(M+1); vis[0][M+1]=true;
    while(que.size()){
      int v=que.front(); que.pop();
      if(v<M)continue;
      for(int nv : g[v]){
        if(vis[0][nv])continue;
        vis[0][nv]=true;
        que.push(nv);
      }
    }
  }
  if(vis[0][M]){
    printf("-1\n");
    return 0;
  }

  {
    queue<int> que;
    que.push(M); vis[1][M]=true;
    while(que.size()){
      int v=que.front(); que.pop();
      if(v<M&&vis[0][v])continue;
      for(int nv : g[v]){
        if(vis[1][nv])continue;
        vis[1][nv]=true;
        que.push(nv);
      }
    }
  }

  D res=sum;
  rep(i,es.size()){
    if(vis[1][es[i].u]&&vis[1][es[i].v]){
      res-=es[i].cost;
    }
  }
  printf("%.10Lf\n", res);

  return 0;
}
accuracy: 1
time_ms: 3680
memory_kb: 7420
final_rank: 11