#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

constexpr double EPS = 1e-9;

struct point {
	double x, y;
	explicit point(double x_ = 0.0, double y_ = 0.0):x(x_), y(y_) {}
	point(const point &p):x(p.x), y(p.y) {}

	point operator+(const point &p) const {
		return point(x + p.x, y + p.y);
	}

	point operator-(const point &p) const {
		return point(x - p.x, y - p.y);
	}

	point operator*(double s) const {
		return point(x * s, y * s);
	}

	bool operator<(const point &p) const {
		return x + EPS < p.x || (abs(x - p.x) < EPS && y + EPS < p.y);
	}

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

double norm(const point &p) {
	return p.x * p.x + p.y * p.y;
}

double abs(const point &p) {
	return sqrt(norm(p));
}

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

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

struct segment {
	point a, b;
	segment(const point &a_, const point &b_):a(a_), b(b_){}
};

int ccw(const point &a, point b, point c) {
	b = b - a;
	c = c - a;
	const double tmp = cross(b, c);
	if(tmp > EPS) return 1; // ccw
	if(tmp < -EPS) return -1; // cw
	if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
	if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
	return 0; //a, c, b 順で一直線上
}

bool intersect(const segment &s, const segment &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;
}


bool intersect(const segment &s, const point &p) {
	return ccw(s.a, s.b, p) == 0;
}

// 先にintersectで交差判定をすること
point crosspoint(const segment &s, const segment &t) {
	const double tmp = cross(s.b - s.a, t.b - t.a);
	if(abs(tmp) < EPS) { // 一直線上
		if(intersect(s, t.a)) return t.a;
		if(intersect(s, t.b)) return t.b;
		if(intersect(t, s.a)) return s.a;
		return s.b;
	}
	return t.a + (t.b - t.a) * (cross(s.b - s.a, s.b - t.a) / tmp);
}

struct edge {
	int to;
	double cost;
	edge(int to_, double cost_):to(to_), cost(cost_) {}
};

void merge(vector<segment> &segments) {
    for(int i = 0; i < static_cast<int>(segments.size());) {
        const auto &s1 = segments[i];
        bool ok = true;
        for(int j = i + 1; j < static_cast<int>(segments.size()); ++j) {
            const auto &s2 = segments[j];
 
            if(intersect(s1, s2) && abs(cross(s1.a - s1.b, s2.a - s2.b)) < EPS) {
				const auto a = min({s1.a, s1.b, s2.a, s2.b});
				const auto b = max({s1.a, s1.b, s2.a, s2.b});
                segments.emplace_back(a, b);
 
                segments.erase(segments.begin() + j);
                segments.erase(segments.begin() + i);
                ok = false;
                break;
            }
        }
        if(ok) ++i;
    }
}

vector<vector<edge>> arrangement(vector<segment> &segments, vector<point> &points) {
	merge(segments);
	const int n = segments.size();

	for(int i = 0; i < n; ++i) {
		const auto &s1 = segments[i];
		points.emplace_back(s1.a);
		points.emplace_back(s1.b);

		for(int j = i + 1; j < n; ++j) {
			const auto &s2 = segments[j];
			if(intersect(s1, s2)) {
				points.emplace_back(crosspoint(s1, s2));
			}
		}
	}

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

	const int V = points.size();
	vector<vector<edge>> G(V);

	for(const auto &s : segments) {
		vector<pair<double, int>> vs;
		for(int i = 0; i < V; ++i) {
			if(intersect(s, points[i])) {
				vs.emplace_back(abs(s.a - points[i]), i);
			}
		}

		sort(vs.begin(), vs.end());
		for(int i = 1; i < static_cast<int>(vs.size()); ++i) {
			const int v = vs[i].second;
			const int u = vs[i - 1].second;
			const double d = vs[i].first - vs[i - 1].first;
			G[v].emplace_back(u, d);
			G[u].emplace_back(v, d);
		}
	}

	return G;
}

inline int get_index(const point &p, const vector<point> &points) {
	return lower_bound(begin(points), end(points), p) - begin(points);
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(10);

	int n, m;
	cin >> n >> m;

	vector<segment> segments;
	segments.reserve(n);

	for(int i = 0; i < n; ++i) {
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		segments.emplace_back(point(x1, y1), point(x2, y2));
	}

	vector<point> stop;
	stop.reserve(m + 2);

	for(int i = 0; i < m; ++i) {
		int x, y;
		cin >> x >> y;
		stop.emplace_back(x, y);
	}

	point source, repair;
	cin >> source.x >> source.y;
	cin >> repair.x >> repair.y;

	vector<point> points(stop);
	points.emplace_back(source);
	points.emplace_back(repair);

	const auto G = arrangement(segments, points);
	const int V = G.size();

	vector<bool> is_stop(V, false);
	for(const auto &p : stop) {
		is_stop[get_index(p, points)] = true;
	}

	vector<bool> visited(V, false);
	queue<int> que;

	const int s = get_index(source, points);
	const int r = get_index(repair, points);
	visited[r] = true;
	que.push(r);

	while(!que.empty()) {
		const int v = que.front();
		que.pop();

		if(v == s) {
			cout << "-1" << endl;
			return EXIT_SUCCESS;
		}

		for(const auto &e : G[v]) {
			if(!visited[e.to] && !is_stop[e.to]) {
				visited[e.to] = true;
				que.push(e.to);
			}
		}
	}

	double ans = 0.0;
	for(const auto &seg : segments) ans += abs(seg.a - seg.b);
	
	vector<bool> used(V, false);
	used[s] = true;
	que.push(s);

	while(!que.empty()) {
		const int v = que.front();
		que.pop();

		if(visited[v]) continue;

		for(const auto &e : G[v]) {
			if(visited[e.to]) continue;

			ans -= e.cost * 0.5;
			
			if(!used[e.to]) {
				used[e.to] = true;
				que.push(e.to);
			}
		}
	}

	cout << ans << endl;

	return EXIT_SUCCESS;
}

Measured memory_bytes: 2808