Problem:
Problem H:
Laser Cutter
Ciel is going to do woodworking. Ciel wants to make a cut in a wooden board using a laser
cutter.
To make it simple, we assume that the board is a two-dimensional plane. There are several
segments on the board along which Ciel wants to cut the board. Each segment has a direction
and Ciel must cut those segments along their directions. Those segments are connected when
you ignore the directions, that is, any two points on the segments are directly or indirectly
connected by the segments.
While the laser cutter is powered on, it emits a laser which hits the board at a point and cuts
the board along its trace. The laser initially points to $(x, y)$. Ciel can conduct the following two
operations:
Move the laser cutter with its power on and cut (a part of) a segment along its direction,
or
Move the laser cutter to any position with its power off. Ciel should not necessarily cut
the whole segment at a time; she can start or stop cutting a segment at any point on the
segments.
Ciel likes to be efficient, so she wants to know the shortest route such that the laser cutter cuts
the whole parts of all the segments and then move back to the initial point. Your task is to
write a program that calculates the minimum total moving distance of the laser cutter.
Input
The first line of the input contains an integer $n$ ($1 \leq n \leq 300$), the number of segments. The
next line contains two integers $x$ and $y$ ($-1,000 \leq x, y \leq 1,000$), which is the initial position
$(x, y)$ of the laser. The $i$-th of the following $n$ lines contains four integers $sx_i$, $sy_i$, $tx_i$ and $ty_i$ ($-1,000 \leq sx_i, sy_i, tx_i, ty_i \leq 1,000$), which indicate that they are the end points of the $i$-th
segment, and that the laser cutter can cut the board in the direction from $(sx_i, sy_i)$ to $(tx_i, ty_i)$.
The input satisfies the following conditions: For all $i$ ($1 \leq i \leq n$), $(sx_i, sy_i) \ne (tx_i, ty_i)$. The
initial point $(x, y)$ lies on at least one of the given segments. For all distinct $i, j$ ($1 \leq i, j \leq n$),
the $i$-th segment and the $j$-th segment share at most one point.
Output
Output a line containing the minimum total moving distance the laser cutter needs to travel to
cut all the segments and move back to the initial point. The absolute error or the relative error
should be less than $10^{-6}$.
Sample Input
3
0 1
0 0 0 1
0 1 0 2
0 2 0 3
Output for the Sample Input
6.0000000000000000
Sample Input
2
0 1
0 0 0 2
-1 1 1 1
Output for the Sample Input
6.8284271247461900
Sample Input
5
0 0
0 0 1 0
1 1 -1 1
-1 1 -1 -1
-1 -1 1 -1
1 -1 1 1
Output for the Sample Input
10.0000000000000000

Submitted solutions:

code_snippet: #include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define cl(x) memset(x,0,sizeof(x))
#define read(x) scanf("%d",&(x));
using namespace std;

inline double sqr(int x){ return x*x; }

const int N=305;

struct PP{
  int x,y;
  friend double dist(PP A,PP B){
    return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
  }
}s[N],t[N];

int n; double w[N][N];
int boy[N]; double sla[N],lx[N],ly[N];
int S[N],T[N];

inline bool match(int u){
  S[u]=1;
  for (int v=1;v<=n;v++){
    if (T[v]) continue;
    if (fabs(lx[u]+ly[v]-w[u][v])<1e-10){
      T[v]=1;
      if (!boy[v] || match(boy[v]))
	return boy[v]=u,1;
    }else
      sla[v]=min(sla[v],lx[u]+ly[v]-w[u][v]);
  }return 0;
}

inline double KM(){
  for (int i=1;i<=n;i++){
    lx[i]=-1<<30;
    for (int j=1;j<=n;j++)
      lx[i]=max(lx[i],w[i][j]);
  }
  for (int i=1;i<=n;i++){
    for (int j=1;j<=n;j++) sla[j]=1<<30;
    while (1){
      cl(S); cl(T); if (match(i)) break;
      double a=1<<30;
      for (int j=1;j<=n;j++) if (!T[j]) a=min(a,sla[j]);
      for (int j=1;j<=n;j++) if (S[j]) lx[j]-=a;
      for (int j=1;j<=n;j++) if (T[j]) ly[j]+=a; else sla[j]-=a;
    }
  }
  double ret=0;  
  for (int i=1;i<=n;i++) if (boy[i]) ret-=w[boy[i]][i];  
  return ret;
}

double ans=0;

int main(){
  read(n); read(s[1].x); read(s[1].y);
  for (int i=1;i<=n;i++){
    read(s[i].x); read(s[i].y);
    read(t[i].x); read(t[i].y);
    ans+=dist(s[i],t[i]);
  }
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      w[i][j]=-dist(t[i],s[j]);
  ans+=KM();
  printf("%.10lf\n",ans);
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3760
final_rank: 2

code_snippet: // AOJ #2724
// Laser Cutter 2025.2.11

#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-9;
 
struct Point { double x, y; };
 
double distP(const Point &a, const Point &b) {
    double dx = a.x - b.x, dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}
 
bool pointOnSegment(const Point &a, const Point &b, const Point &p) {
    double cross = (p.x - a.x) * (b.y - a.y) - (p.y - a.y) * (b.x - a.x);
    if (fabs(cross) > EPS) return false;
    if (p.x < min(a.x, b.x) - EPS || p.x > max(a.x, b.x) + EPS) return false;
    if (p.y < min(a.y, b.y) - EPS || p.y > max(a.y, b.y) + EPS) return false;
    return true;
}
 
struct Segment {
    Point s, t;
    bool special;
};
 
struct Arc {
    Point u, v;
    double cost;
};
 
string pointKey(const Point &p) {
    ostringstream oss;
    oss << fixed << setprecision(12) << p.x << "_" << p.y;
    return oss.str();
}
 
double hungarian(const vector<vector<double>> &cost) {
    int n = cost.size();
    const double INF = 1e9;
    vector<double> u(n+1, 0), v(n+1, 0);
    vector<int> p(n+1, 0), way(n+1, 0);
    for (int i = 1; i <= n; i++) {
        p[0] = i;
        vector<double> minv(n+1, INF);
        vector<bool> used(n+1, false);
        int j0 = 0;
        do {
            used[j0] = true;
            int i0 = p[j0], j1 = 0;
            double delta = INF;
            for (int j = 1; j <= n; j++) {
                if (!used[j]) {
                    double cur = cost[i0-1][j-1] - u[i0] - v[j];
                    if (cur < minv[j]) {
                        minv[j] = cur;
                        way[j] = j0;
                    }
                    if (minv[j] < delta) {
                        delta = minv[j];
                        j1 = j;
                    }
                }
            }
            for (int j = 0; j <= n; j++) {
                if (used[j]) {
                    u[p[j]] += delta;
                    v[j] -= delta;
                } else {
                    minv[j] -= delta;
                }
            }
            j0 = j1;
        } while (p[j0] != 0);
        do {
            int j1 = way[j0];
            p[j0] = p[j1];
            j0 = j1;
        } while (j0);
    }
    return -v[0];
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int n;
    cin >> n;
    Point init;
    cin >> init.x >> init.y;
 
    vector<Segment> segs(n);
    for (int i = 0; i < n; i++){
        cin >> segs[i].s.x >> segs[i].s.y >> segs[i].t.x >> segs[i].t.y;
        if(pointOnSegment(segs[i].s, segs[i].t, init)){
            if((fabs(init.x - segs[i].s.x) < EPS && fabs(init.y - segs[i].s.y) < EPS) ||
               (fabs(init.x - segs[i].t.x) < EPS && fabs(init.y - segs[i].t.y) < EPS))
                segs[i].special = false;
            else segs[i].special = true;
        } else   segs[i].special = false;
    }
 
    vector<Arc> arcs;
    double reqSum = 0.0;
    for (int i = 0; i < n; i++){
        if(segs[i].special){
            Arc a1, a2;
            a1.u = segs[i].s; a1.v = init;
            a1.cost = distP(a1.u, a1.v);
            a2.u = init; a2.v = segs[i].t;
            a2.cost = distP(a2.u, a2.v);
            arcs.push_back(a1);
            arcs.push_back(a2);
            reqSum += a1.cost + a2.cost;
        } else {
            Arc a;
            a.u = segs[i].s; a.v = segs[i].t;
            a.cost = distP(a.u, a.v);
            arcs.push_back(a);
            reqSum += a.cost;
        }
    }
 
    unordered_map<string, int> vid;
    vector<Point> vertices;
    auto addVertex = [&](const Point &p) -> int {
        string key = pointKey(p);
        if(vid.find(key) == vid.end()){
            int idx = vertices.size();
            vertices.push_back(p);
            vid[key] = idx;
            return idx;
        }
        return vid[key];
    };
    for (auto &arc : arcs) {
        addVertex(arc.u);
        addVertex(arc.v);
    }
    int initIndex = addVertex(init);
 
    int V = vertices.size();
    vector<int> imbalance(V, 0);
    for (auto &arc : arcs){
        int u = addVertex(arc.u);
        int v = addVertex(arc.v);
        imbalance[u] += 1;
        imbalance[v] -= 1;
    }
 
    vector<int> posList, negList;
    for (int i = 0; i < V; i++){
        if(imbalance[i] > 0){
            for (int k = 0; k < imbalance[i]; k++)
                posList.push_back(i);
        } else if(imbalance[i] < 0){
            for (int k = 0; k < -imbalance[i]; k++)
                negList.push_back(i);
        }
    }
    int m = posList.size();
    if(m == 0){
        cout << fixed << setprecision(16) << reqSum << endl;
        return 0;
    }
 
    vector<vector<double>> cost(m, vector<double>(m, 0));
    for (int i = 0; i < m; i++){
        for (int j = 0; j < m; j++){
            cost[i][j] = distP(vertices[posList[i]], vertices[negList[j]]);
        }
    }
    double extraCost = hungarian(cost);
    double ans = reqSum + extraCost;
    cout << fixed << setprecision(16) << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4164
final_rank: 1

code_snippet: // AOJ #2724
// Laser Cutter 2025.2.11

#include <bits/stdc++.h>
using namespace std;
 
const double EPS = 1e-9;
 
struct Point { double x, y; };
 
double distP(const Point &a, const Point &b) {
    double dx = a.x - b.x, dy = a.y - b.y;
    return sqrt(dx*dx + dy*dy);
}
 
bool pointOnSegment(const Point &a, const Point &b, const Point &p) {
    double cross = (p.x - a.x)*(b.y - a.y) - (p.y - a.y)*(b.x - a.x);
    if(fabs(cross) > EPS) return false;
    if(p.x < min(a.x, b.x) - EPS || p.x > max(a.x, b.x) + EPS) return false;
    if(p.y < min(a.y, b.y) - EPS || p.y > max(a.y, b.y) + EPS) return false;
    return true;
}
 
struct Segment {
    Point s, t;
    bool special;
};
 
struct Arc {
    Point u, v;
    double cost;
};
 
string pointKey(const Point &p) {
    ostringstream oss;
    oss << fixed << setprecision(12) << p.x << "_" << p.y;
    return oss.str();
}
 
struct Edge {
    int to, rev;
    int cap;
    double cost;
};
 
struct MinCostFlow {
    int n;
    vector<vector<Edge>> graph;
    vector<double> potential, dist;
    vector<int> prevV, prevE;
 
    MinCostFlow(int n): n(n), graph(n), potential(n,0), dist(n), prevV(n), prevE(n) {}
 
    void add_edge(int s, int t, int cap, double cost) {
        Edge a = {t, (int)graph[t].size(), cap, cost};
        Edge b = {s, (int)graph[s].size(), 0, -cost};
        graph[s].push_back(a);
        graph[t].push_back(b);
    }
 
    double min_cost_flow(int s, int t, int f) {
        const double INF = 1e9;
        double res = 0;
        while(f > 0) {
            priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;
            fill(dist.begin(), dist.end(), INF);
            dist[s] = 0;
            pq.push({0, s});
            while(!pq.empty()){
                auto p = pq.top(); pq.pop();
                int v = p.second;
                if(dist[v] < p.first - EPS) continue;
                for (int i=0; i< graph[v].size(); i++){
                    Edge &e = graph[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + potential[v] - potential[e.to] + EPS){
                        dist[e.to] = dist[v] + e.cost + potential[v] - potential[e.to];
                        prevV[e.to] = v;
                        prevE[e.to] = i;
                        pq.push({dist[e.to], e.to});
                    }
                }
            }
            if(dist[t] > INF/2) return -1;
            for(int v=0; v<n; v++){
                if(dist[v] < INF)
                    potential[v] += dist[v];
            }
            int addFlow = f;
            for(int v = t; v != s; v = prevV[v]){
                addFlow = min(addFlow, graph[prevV[v]][prevE[v]].cap);
            }
            f -= addFlow;
            res += addFlow * potential[t];
            for(int v = t; v != s; v = prevV[v]){
                Edge &e = graph[prevV[v]][prevE[v]];
                e.cap -= addFlow;
                graph[v][e.rev].cap += addFlow;
            }
        }
        return res;
    }
};
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int n;
    cin >> n;
    Point init;
    cin >> init.x >> init.y;
 
    vector<Segment> segs(n);
    for (int i = 0; i < n; i++){
        cin >> segs[i].s.x >> segs[i].s.y >> segs[i].t.x >> segs[i].t.y;
        if(pointOnSegment(segs[i].s, segs[i].t, init)) {
            if(fabs(init.x - segs[i].s.x) < EPS && fabs(init.y - segs[i].s.y) < EPS)
                segs[i].special = false;
            else if(fabs(init.x - segs[i].t.x) < EPS && fabs(init.y - segs[i].t.y) < EPS)
                segs[i].special = false;
            else segs[i].special = true;
        } else  segs[i].special = false;
    }
 
    vector<Arc> arcs;
    double reqSum = 0.0;
    for (int i = 0; i < n; i++){
        if(segs[i].special){
            Arc a1, a2;
            a1.u = segs[i].s; a1.v = init;
            a1.cost = distP(a1.u, a1.v);
            a2.u = init; a2.v = segs[i].t;
            a2.cost = distP(a2.u, a2.v);
            arcs.push_back(a1);
            arcs.push_back(a2);
            reqSum += a1.cost + a2.cost;
        } else {
            Arc a;
            a.u = segs[i].s; a.v = segs[i].t;
            a.cost = distP(a.u, a.v);
            arcs.push_back(a);
            reqSum += a.cost;
        }
    }
 
    unordered_map<string, int> vid;
    vector<Point> vertices;
    auto addVertex = [&](const Point &p) -> int {
        string key = pointKey(p);
        if(vid.find(key) == vid.end()){
            int idx = vertices.size();
            vertices.push_back(p);
            vid[key] = idx;
            return idx;
        }
        return vid[key];
    };
    for (auto &arc : arcs) {
        addVertex(arc.u);
        addVertex(arc.v);
    }
    int initIndex = addVertex(init);
 
    int V = vertices.size();
    vector<int> imbalance(V, 0);
    for (auto &arc : arcs){
        int u = addVertex(arc.u);
        int v = addVertex(arc.v);
        imbalance[u] += 1;
        imbalance[v] -= 1;
    }
 
    int N = V + 2;
    int S = V, T = V + 1;
    MinCostFlow mcf(N);
    int totalSupply = 0;
    for (int i = 0; i < V; i++){
        if(imbalance[i] > 0) {
            mcf.add_edge(S, i, imbalance[i], 0.0);
            totalSupply += imbalance[i];
        } else if(imbalance[i] < 0)
            mcf.add_edge(i, T, -imbalance[i], 0.0);
    }
    for (int i = 0; i < V; i++){
        if(imbalance[i] > 0){
            for (int j = 0; j < V; j++){
                if(imbalance[j] < 0){
                    double d = distP(vertices[i], vertices[j]);
                    mcf.add_edge(i, j, 1000, d);
                }
            }
        }
    }
    double extraCost = mcf.min_cost_flow(S, T, totalSupply);
    double ans = reqSum + extraCost;
    cout << fixed << setprecision(16) << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 10488
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=300005;
const ll INF=1LL<<60;

//https://kopricky.github.io/code/NetworkFlow/hungarian.html

template<typename T> class Hungarian
{
private:
    const int U, V;
    vector<vector<int> > graph;
    vector<T> dual;
    vector<int> alloc, rev_alloc, prev;
    const vector<vector<T> >& cost;
    int matching_size;
    T diff(const int i, const int j){
        return cost[i][j] - dual[i] - dual[U + j];
    }
    void init_feasible_dual(){
        for(int i = 0; i < U; ++i){
            dual[i] = 0;
            for(int j = 0; j < V; ++j){
                dual[U + j] = min(dual[U + j], cost[i][j]);
            }
        }
    }
    void construct_graph(){
        for(int i = 0; i < U; ++i){
            for(int j = 0; j < V; ++j){
                graph[i][j] = (diff(i, j) == 0 && rev_alloc[j] != i);
            }
        }
    }
    bool find_augmenting_path(const int cur, const int prv, int& pos){
        prev[cur] = prv;
        if(cur >= U){
            if(rev_alloc[cur - U] < 0) return true;
            if(find_augmenting_path(rev_alloc[cur - U], cur, pos)){
                graph[rev_alloc[cur - U]][cur - U] = 1;
                return true;
            }
        }else{
            const int MX = (alloc[cur] < 0 && pos == U) ? U : V;
            for(int i = 0; i < MX; ++i){
                if(graph[cur][i] && prev[U + i] < 0 && find_augmenting_path(U + i, cur, pos)){
                    graph[cur][i] = 0, alloc[cur] = i, rev_alloc[i] = cur;
                    return true;
                }
            }
            if(alloc[cur] < 0 && pos < U){
                graph[cur][pos] = 0, alloc[cur] = pos, rev_alloc[pos] = cur, prev[U + pos] = cur;
                return ++pos, true;
            }
        }
        return false;
    }
    void update_dual(const T delta){
        for(int i = 0; i < U; ++i) if(prev[i] >= 0) dual[i] += delta;
        for(int i = U; i < U + V; ++i) if(prev[i] >= 0) dual[i] -= delta;
    }
    void maximum_matching(bool initial=false){
        int pos = initial ? V : U;
        for(bool update = false;; update = false){
            fill(prev.begin(), prev.end(), -1);
            for(int i = 0; i < U; ++i){
                if(alloc[i] < 0 && find_augmenting_path(i, 2 * U, pos)){
                    update = true, ++matching_size;
                    break;
                }
            }
            if(!update) break;
        }
    }
    int dfs(const int cur, const int prv, vector<int>& new_ver){
        prev[cur] = prv;
        if(cur >= U){
            if(rev_alloc[cur - U] < 0) return cur;
            else return dfs(rev_alloc[cur - U], cur, new_ver);
        }else{
            new_ver.push_back(cur);
            for(int i = 0; i < V; ++i){
                if(graph[cur][i] && prev[U + i] < 0){
                    const int res = dfs(U + i, cur, new_ver);
                    if(res >= U) return res;
                }
            }
        }
        return -1;
    }
    int increase_matching(const vector<pair<int, int> >& vec, vector<int>& new_ver){
        for(const auto& e : vec){
            if(prev[e.first] < 0){
                const int res = dfs(e.first, e.second, new_ver);
                if(res >= U) return res;
            }
        }
        return -1;
    }
    void hint_increment(int cur){
        while(prev[cur] != 2 * U){
            if(cur >= U){
                graph[prev[cur]][cur - U] = 0, alloc[prev[cur]] = cur - U, rev_alloc[cur - U] = prev[cur];
            }else{
                graph[cur][prev[cur] - U] = 1;
            }
            cur = prev[cur];
        }
    }
public:
    Hungarian(const vector<vector<T> >& _cost)
    : U((int)_cost.size()), V((int)_cost[0].size()), graph(U, vector<int>(U, 1)), dual(U + V, numeric_limits<T>::max()),
    alloc(U, -1), rev_alloc(U, -1), prev(2 * U), cost{_cost}, matching_size(0){
        assert(U >= V);
    }
    pair<T, vector<int> > solve(){
        init_feasible_dual(), construct_graph();
        bool end = false;
        maximum_matching(true);
        while(matching_size < U){
            vector<pair<T, int> > cand(V, {numeric_limits<T>::max(), numeric_limits<int>::max()});
            for(int i = 0; i < U; ++i){
                if(prev[i] < 0) continue;
                for(int j = 0; j < V; ++j){
                    if(prev[U + j] >= 0) continue;
                    cand[j] = min(cand[j], {diff(i, j), i});
                }
            }
            while(true){
                T delta = numeric_limits<T>::max();
                for(int i = 0; i < V; ++i){
                    if(prev[U + i] >= 0) continue;
                    delta = min(delta, cand[i].first);
                }
                update_dual(delta);
                vector<pair<int, int> > vec;
                vector<int> new_ver;
                for(int i = 0; i < V; ++i){
                    if(prev[U + i] >= 0) continue;
                    if((cand[i].first -= delta) == 0) vec.emplace_back(U + i, cand[i].second);
                }
                int res = increase_matching(vec, new_ver);
                if(res >= U){
                    hint_increment(res);
                    if(++matching_size == U) end = true;
                    else construct_graph();
                    break;
                }else{
                    for(const int v : new_ver){
                        for(int i = 0; i < V; ++i){
                            if(prev[U + i] >= 0) continue;
                            cand[i] = min(cand[i], {diff(v, i), v});
                        }
                    }
                }
            }
            if(!end) maximum_matching();
        }
        T total_cost = 0;
        for(int i = 0; i < U; ++i){
            if(alloc[i] < V) total_cost += cost[i][alloc[i]];
            else alloc[i] = -1;
        }
        return make_pair(total_cost, alloc);
    }
};

//幾何ライブラリ
// define double ll をするときは Point の < と == も書き換えよう！

const double eps=1e-8;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)

double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}

class Point{
public:
    double x,y;
    
    Point(double x=0,double y=0):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 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+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
        //return x<p.x||(x==p.x&&y<p.y);
    }
    
    bool operator == (const Point &p)const{
        return fabs(x-p.x)<eps/100000&&fabs(y-p.y)<eps/100000;
        //return x==p.x&&y==p.y;
    }
};

typedef Point Vector;

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;
}

struct Segment{
    Point p1,p2;
};

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;
}

Point turn(Point p,Point c,double pi){
    double q=atan2(p.y-c.y,p.x-c.x);
    q+=pi;
    p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
    
    return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan

//p0,p1,p2の順に見たときどうなるか？

static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int on_segment=0;

int ccw(Point p0,Point p1,Point p2){
    Vector a=p1-p0;
    Vector b=p2-p0;
    
    if(cross(a,b)>eps) return counter_clockwise;
    if(cross(a,b)<-eps) return clockwise;
    if(dot(a,b)<-eps) return online_back;
    if(a.norm()<b.norm()) return online_front;
    
    return on_segment;
}

bool intersect(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 intersect(Segment s1,Segment s2){
    return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool overlap(Segment s1,Segment s2){
    int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
    if(a&1||b&1) return 0;
    if(a==2){
        if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
        else return 0;
    }
    if(a==-2){
        if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
        else return 0;
    }
    if(a==0){
        if(s1.p1==s2.p1){
            if(b!=2) return 1;
            else return 0;
        }
        else if(s1.p2==s2.p1){
            if(b!=-2) return 1;
            else return 0;
        }
        else return 1;
    }
    return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか

typedef Segment Line;

double getDistance(Point a,Point b){
    return abs(a-b);
}

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 getDistance(Segment s1,Segment s2){
    if(intersect(s1,s2)) return 0.0;
    return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}

Point getCrossPointS(Segment s1,Segment s2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    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 getCrossPointL(Line l1,Line l2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    
    return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}

Segment ParallelSegment(Segment s,double d){
    Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
    v=v/abs(v);
    
    s.p1=s.p1+v*d;
    s.p2=s.p2+v*d;
    
    return s;
}

Point naisin(Point p1,Point p2,Point p3){
    if(p1==p2&&p2==p3&&p3==p1) return p1;
    
    return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}

Point naisin(Line l1,Line l2,Line l3){
    //平行でない前提
    
    Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
    return naisin(p1,p2,p3);
}

//ネットの適当を書いたのであってるか全く知りません→あってそう

class Circle{
public:
    Point c;
    double r;
    Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

Point CircleCenter(Point a,Point b,Point c){
    Point u=a-b,v=a-c;
    double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
    
    Point res;
    if(cross(u,v)==0.0){
        res.x=1e9;
        res.y=1e9;
        
        return res;
    }
    res.x=(m1*v.y-m2*u.y)/cross(u,v);
    res.y=(m1*v.x-m2*u.x)/cross(v,u);
    
    return res;
}
//3点を通る円の中心を返す

//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3

int not_intersect(Circle c1,Circle c2){
    double d=getDistance(c1.c,c2.c);
    double r1=c1.r,r2=c2.r;
    if(r1<r2){
        if(d<(r2-r1)) return 1;
    }
    if(r1>r2){
        if(d<(r1-r2)) return 2;
    }
    if(d<=r1+r2) return 0;
    else return 3;
}

pair<Point,Point> segCrossPpoints(Circle c,Line l){
    //assert(intersect(c,l));
    Vector pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    return make_pair(pr+e*base,pr-e*base);
}

double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}

//inside(outside)

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    //assert(intersect(c1,c2));
    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);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

vector<Line> Commontangent(Circle c1,Circle c2){
    vector<Line> res;
    Point p=c2.c-c1.c;
    
    if(abs(p)>=(c1.r+c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    if(abs(p)>=abs(c1.r-c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    return res;
}

typedef vector<Point> Polygon;

/*
 IN 2
 ON 1
 OUT 0
 */

int contains(Polygon g,Point p){
    int n=int(g.size());
    bool x=false;
    for(int i=0;i<n;i++){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(a.y>b.y) swap(a,b);
        if(a.y<eps&&0<b.y&&cross(a,b)<0) x=!x;
        if(abs(cross(a,b))<eps&&dot(a,b)<eps) return 1;
    }
    return (x?2:0);
}

Polygon andrewScan(Polygon s,bool ok){
    Polygon u,l;
    sort(all(s));
    
    if(int(s.size())<3) return s;
    int n=int(s.size());
    
    u.push_back(s[0]);
    u.push_back(s[1]);
    
    l.push_back(s[n-1]);
    l.push_back(s[n-2]);
    
    if(ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    if(!ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    reverse(all(l));
    
    for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
    
    return l;
}//ok==1なら辺の上も含める

Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon Q;
    for(int i=0;i<si(P);i++){
        Point A=P[i],B=P[(i+1)%si(P)];
        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(getCrossPointL(Line{A,B},l));
    }
    return Q;
}

double area(Point a,Point b,Point c){
    b=b-a;
    c=c-a;
    return abs(b.x*c.y-b.y*c.x)/2.0;
}

/*
 
 ll area(Polygon P){
 ll sum=0;
 for(int i=0;i<si(P);i++){
 sum+=cross(P[i],P[(i+1)%si(P)]);
 }
 return abs(sum);
 }
 
 */

// 倍

double area(Polygon &P){
    if(si(P)==0) return 0.0;
    double res=0;
    Point c={0.0,0.0};
    for(int i=0;i<si(P);i++){
        c=c+P[i];
    }
    c=c/si(P);
    
    for(int i=0;i<si(P);i++){
        res+=area(c,P[i],P[(i+1)%si(P)]);
    }
    
    return res;
}

ll gcd(ll a,ll b){
    if(b==0) return a;
    return gcd(b,a%b);
}

pair<Point,Vector> perpendicular_bisector(Point a,Point b){
    Point c=(a+b)/2;
    Vector v=b-c;
    swap(v.x,v.y);
    v.x*=-1;
    
    Point p=c;
    if(v.x==0){
        v.y=1;
        p.y=0;
    }
    else if(v.y==0){
        v.x=1;
        p.x=0;
    }
    else{
        if(v.x<0){
            v.x*=-1;
            v.y*=-1;
        }
        ll g=gcd(abs(ll(v.x)),abs(ll(v.y)));
        v.x/=g;
        v.y/=g;
        if(p.x>=0){
            ll d=p.x/v.x;
            p=p-v*d;
        }else{
            ll d=abs(p.x)/v.x;
            p=p+v*d;
            
            if(p.x<0){
                p=p+v;
            }
        }
    }
    
    return mp(p,v);
}
//2倍するなりして整数にしておくこと

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    Point st;cin>>st.x>>st.y;
    double ans=0;
    vector<Segment> S(N);
    for(int i=0;i<N;i++){
        cin>>S[i].p1.x>>S[i].p1.y>>S[i].p2.x>>S[i].p2.y;
        ans+=getDistance(S[i].p1,S[i].p2);
    }
    
    vector<vector<double>> cost(N,vector<double>(N));
    
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            cost[i][j]=getDistance(S[i].p2,S[j].p1);
        }
    }
    
    Hungarian<double> G(cost);
    
    ans+=G.solve().fi;
    
    cout<<fixed<<setprecision(25)<<ans<<endl;
}
accuracy: 1
time_ms: 30
memory_kb: 4672
final_rank: 3

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#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 = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#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 long 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 << 2;
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];
}

ll gcd(ll a, ll b) {
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

template<typename T>
struct mcf {
private:
	struct edge {
		int to, cap; T cost; int rev;
	};
	vector<vector<edge>> G;
	vector<P> par;
	vector<T> dist;
	T inf = INF;
public:
	mcf(int n) {
		G.resize(n);
		par.resize(n);
		dist.resize(n);
	}
	void add_edge(int from, int to, int cap, T cost) {
		G[from].push_back({ to,cap,cost,(int)G[to].size() });
		G[to].push_back({ from,0,-cost,(int)G[from].size() - 1 });
	}
	pair<T,int> minimum_road(int s, int t) {
		fill(all(par), P{ -1,-1 });
		fill(all(dist), inf);
		dist[s] = 0;
		priority_queue<pair<T,int>, vector<pair<T, int>>, greater<pair<T, int>>> q; 
		q.push({ 0,s });
		while (!q.empty()) {
			pair<T,int> p = q.top(); q.pop();
			int id = p.second;
			if (id == t)continue;
			if (p.first > dist[id])continue;
			rep(j, G[id].size()) {
				if (G[id][j].cap > 0) {
					int to = G[id][j].to;
					T nd = p.first + G[id][j].cost;
					if (nd < dist[to]) {
						dist[to] = nd;
						par[to] = { id,j };
						q.push({ dist[to],to });
					}
				}
			}
		}
		int cur = t;
		int f = mod;
		while (cur != s) {
			int p = par[cur].first, j = par[cur].second;
			if (p < 0)return { -1,-1 };
			f = min(f, G[p][j].cap);
			cur = p;
		}
		cur = t;
		while (cur != s) {
			int p = par[cur].first, j = par[cur].second;
			if (p < 0)return { -1,-1 };
			G[p][j].cap -= f;
			if (G[p][j].rev >= 0) {
				G[cur][G[p][j].rev].cap += f;
			}
			cur = p;
		}
		return { dist[t],f };
	}
	T minimum_cost_flow(int s, int t, int k) {
		T ret = 0;
		rep(i, k) {
			pair<T,int> z = minimum_road(s, t);
			if (z.first < 0)return -1;
			if (k - i <= z.second) {
				ret += z.first * (k - i); break;
			}
			i += z.second - 1;
			ret += z.first * z.second;
		}
		return ret;
	}
};

void solve() {
	int n; cin >> n;
	int sx, sy; cin >> sx >> sy;
	vector<int> lx(n), ly(n), rx(n), ry(n);
	rep(i, n) {
		cin >> lx[i] >> ly[i] >> rx[i] >> ry[i];
	}
	mcf<ld> mc(2 * n + 2);
	rep(i, n) {
		rep(j, n) {
			int dx = rx[j] - lx[i];
			int dy = ry[j] - ly[i];
			ld cost = sqrt(dx * dx + dy * dy);
			mc.add_edge(i, j + n, 1, cost);
		}
	}
	rep(i, n) {
		mc.add_edge(2 * n, i, 1, 0);
		mc.add_edge(i + n, 2 * n + 1, 1, 0);
	}
	ld ans = mc.minimum_cost_flow(2 * n, 2 * n + 1,n);
	rep(i, n) {
		int dx = rx[i] - lx[i];
		int dy = ry[i] - ly[i];
		ld cost = sqrt(dx * dx + dy * dy);
		ans += cost;
	}
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(8);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
		solve();
	return 0;
}
accuracy: 1
time_ms: 1440
memory_kb: 15712
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e20;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()
typedef complex<double> P;
typedef vector<P> VP;

template<typename T>
struct MincostFlow{
    struct edge{
        int to, rev;
        int cap;
        T cost;
        edge(int to, int rev, int cap, T cost)
            :to(to),rev(rev),cap(cap),cost(cost){}
        edge(){}
    };
    
    int n;
    T zero;
    T inf;
    vector<vector<edge>> graph;

    MincostFlow(int n, T zero, T inf):n(n),zero(zero),inf(inf){
        graph.resize(n);
    }
    void add_edge(int from, int to, int cap, T cost){
        graph[from].emplace_back(to, graph[to].size(), cap, cost);
        graph[to].emplace_back(from, (int)graph[from].size()-1, 0, -cost);
    }
    T exec(int s, int g, int f){
        T res = zero;
        while(f > 0){
            vector<int> prevv(n), preve(n);
            vector<T> mincost(n, inf);
            mincost[s] = zero;
            while(1){
                bool update = false;
                for(int i=0; i<n; i++){
                    if(mincost[i] == inf) continue;
                    for(int j=0; j<(int)graph[i].size(); j++){
                        edge &e = graph[i][j];
                        if(e.cap>0 && mincost[i] +e.cost +EPS < mincost[e.to]){
                            mincost[e.to] = mincost[i] +e.cost;
                            prevv[e.to] = i;
                            preve[e.to] = j;
                            update = true;
                        }
                    }
                }
                if(!update) break;
            }
            if(mincost[g] == inf){
                return inf;
            }
         
            int d = f;
            for(int v=g; v!=s; v=prevv[v]){
                d = min(d, graph[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d*mincost[g];
            for(int v=g; v!=s; v=prevv[v]){
                edge &e = graph[prevv[v]][preve[v]];
                e.cap -= d;
                graph[v][e.rev].cap += d;
            }
        }
        return res;
    }
};

int main(){
    int n;
    cin >> n;
    int x,y;
    cin >> x >> y;
    vector<VP> l(n, VP(2));
    double len = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<2; j++){
            cin >> x >> y;
            l[i][j] = P(x, y);
        }
        len += abs(l[i][1]-l[i][0]);
    }
    
    MincostFlow<double> mcf(2*n+2, 0, INF);
    for(int i=0; i<n; i++){
        mcf.add_edge(2*n, i, 1, 0);
        mcf.add_edge(n+i, 2*n+1, 1, 0);
    }
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            mcf.add_edge(i, n+j, 1, abs(l[i][1]-l[j][0]));
        }
    }
    cout << fixed << setprecision(10);
    cout << mcf.exec(2*n, 2*n+1, n) +len << endl;
    return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 10232
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;
constexpr double eps = 1e-10;

struct edge {
    int to, rev, cap;
    double cost;
    edge(int t, int c, double ct, int r) : to(t), rev(r), cap(c), cost(ct) {}
};
using graph = vector<vector<edge>>;

void add_edge(graph& g, int from, int to, int cap, double cost) {
    g[from].emplace_back(to, cap, cost, g[to].size());
    g[to].emplace_back(from, 0, -cost, g[from].size() - 1);
}

double min_cost_flow(graph& g, int s, int t, int f) {
    using P = pair<double, int>;
    const double inf = 1e18;
    double res = 0;
    vector<double > h(g.size()), dist(g.size());
    vector<int> prevv(g.size()), preve(g.size());
    while(f > 0) {
        priority_queue<P, vector<P>, greater<>> que;
        fill(begin(dist), end(dist), inf);
        dist[s] = 0;
        que.emplace(0, s);
        while(!que.empty()) {
            const auto cur_d = que.top().first;
            const int v = que.top().second;
            que.pop();
            if(dist[v] < cur_d) continue;
            for(int i = 0; i < (int)g[v].size(); ++i) {
                auto& e = g[v][i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to] + eps) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.emplace(dist[e.to], e.to);
                }
            }
        }
        if(dist[t] == inf) return -1;
        for(int v = 0; v < (int)g.size(); ++v) {
            h[v] += dist[v];
        }

        auto d = f;
        for(int v = t; v != s; v = prevv[v]) {
            d = min(d, g[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for(int v = t; v != s; v = prevv[v]) {
            auto& e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}

int main() {
    int n; cin >> n;
    int ix, iy; cin >> ix >> iy;
    vector<int> sx(n), sy(n), gx(n), gy(n);
    for(int i = 0; i < n; ++i) {
        cin >> sx[i] >> sy[i] >> gx[i] >> gy[i];
    }

    double ans = 0;
    for(int i = 0; i < n; ++i) {
        ans += hypot(gx[i] - sx[i], gy[i] - sy[i]);
    }
    graph g(n * 2 + 2);
    const int src = n * 2, sink = n * 2 + 1;
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < n; ++j) {
            add_edge(g, i, j + n, 1, hypot(sx[j] - gx[i], sy[j] - gy[i]));
        }
        add_edge(g, src, i, 1, 0);
        add_edge(g, i + n, sink, 1, 0);
    }
    ans += min_cost_flow(g, src, sink, n);

    cout << fixed << setprecision(10) << ans << endl;
}
accuracy: 1
time_ms: 180
memory_kb: 10040
final_rank: 7

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 2005
#define ADD 1000


//辺を表す構造体{行先、容量、コスト、逆辺のインデックス}
struct Edge{
	Edge(int arg_to,int arg_capacity,double arg_cost,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		cost = arg_cost;
		rev_index = arg_rev_index;
	}

	int to,capacity,rev_index;
	double cost;
};

struct Point{
	void set(int arg_x,int arg_y){
		x = arg_x;
		y = arg_y;
	}
	int x,y;
};

struct Info{
	Info(int arg_x,int arg_y,int arg_diff){
		x = arg_x;
		y = arg_y;
		diff = arg_diff;
	}
	int x,y,diff;
};

int V; //頂点数
vector<Edge> G[NUM]; //グラフの隣接リスト表現
double dist[NUM]; //最短距離
int pre_node[NUM],pre_edge[NUM]; //直前の頂点と辺

int num_line;
int in_num[NUM][NUM],out_num[NUM][NUM];
int point_index;
int index_FROM[NUM],index_TO[NUM];
Point start;
Point point[NUM];
vector<Info> FROM,TO;

//fromからtoへ向かう容量capacity,コストcostの辺をグラフに追加する
void add_edge(int from,int to,int capacity,double cost){
	G[from].push_back(Edge(to,capacity,cost,G[to].size()));
	G[to].push_back(Edge(from,0,-cost,G[from].size()-1));
}

//sourceからsinkへの、流量flowの最小費用流を求める
//流せない場合は-1を返す
double min_cost_flow(int source,int sink,int flow){

	double ret = 0;
	while(flow > 0){
		//ベルマンフォード方により、source-sink間最短経路を求める
		for(int i = 0; i < V; i++)dist[i] = BIG_NUM;
		dist[source] = 0;
		bool update = true;

		int dog = 0;

		while(update){

			update = false;
			for(int node_id = 0; node_id < V; node_id++){
				if(fabs(dist[node_id]-BIG_NUM) < EPS)continue;
				for(int i = 0; i < G[node_id].size(); i++){
					Edge &e = G[node_id][i];
					if(e.capacity > 0 && dist[e.to] > dist[node_id]+e.cost+EPS){
						dist[e.to] = dist[node_id]+e.cost; //node_idを経由した方が早い場合
						pre_node[e.to] = node_id;
						pre_edge[e.to] = i;
						update = true;
					}
				}
			}
		}

		if(fabs(dist[sink]-BIG_NUM) < EPS){
			//これ以上流せない
			return -1;
		}

		//source-sink間最短路に沿って目いっぱい流す
		int tmp_flow = flow;

		int dk = 0;

		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){

			tmp_flow = min(tmp_flow,G[pre_node[node_id]][pre_edge[node_id]].capacity);
		}
		flow -= tmp_flow;

		ret += tmp_flow*dist[sink];
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			Edge &e = G[pre_node[node_id]][pre_edge[node_id]];
			e.capacity -= tmp_flow;
			G[node_id][e.rev_index].capacity += tmp_flow;
		}
	}
	return ret;
}


void add(Point& tmp){

	tmp.x += ADD;
	tmp.y += ADD;
}

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));
}

double calc_dist(Info a,Info b){

	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main(){

	for(int x = 0; x < NUM; x++){
		for(int y = 0; y < NUM; y++){
			in_num[x][y] = 0;
			out_num[x][y] = 0;
		}
	}

	scanf("%d",&num_line);
	scanf("%d %d",&start.x,&start.y);

	add(start);

	point_index = 0;
	double ans = 0;

	for(int loop = 0; loop < num_line; loop++){

		//from
		scanf("%d %d",&point[point_index].x,&point[point_index].y);
		add(point[point_index]);
		out_num[point[point_index].x][point[point_index].y] += 1;

		point_index++;

		//to
		scanf("%d %d",&point[point_index].x,&point[point_index].y);
		add(point[point_index]);
		in_num[point[point_index].x][point[point_index].y] += 1;

		ans += calc_dist(point[point_index-1],point[point_index]);

		point_index++;
	}

	for(int x = 0; x < NUM; x++){
		for(int y = 0; y < NUM; y++){
			if(in_num[x][y] == out_num[x][y])continue;

			if(in_num[x][y] > out_num[x][y]){

				FROM.push_back(Info(x,y,in_num[x][y]-out_num[x][y]));

			}else{

				TO.push_back(Info(x,y,out_num[x][y]-in_num[x][y]));
			}
		}
	}

	int FLOW = 0;
	int source = 0,sink = 1;
	int index = 2;

	for(int i = 0; i < FROM.size(); i++){

		index_FROM[i] = index++;
		FLOW += FROM[i].diff;
		add_edge(source,index_FROM[i],FROM[i].diff,0);
	}

	int to_sum = 0;

	for(int i = 0; i < TO.size(); i++){

		index_TO[i] = index++;
		add_edge(index_TO[i],sink,TO[i].diff,0);
		to_sum += TO[i].diff;
	}

	for(int i = 0; i < FROM.size(); i++){
		for(int k = 0; k < TO.size(); k++){
			add_edge(index_FROM[i],index_TO[k],1,calc_dist(FROM[i],TO[k]));
		}
	}

	V = index;

	ans += min_cost_flow(source,sink,FLOW);

	printf("%.10lf\n",ans);

	return 0;
}
accuracy: 1
time_ms: 470
memory_kb: 41172
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

// (行き先, 容量, コスト, 逆辺)
struct edge{
    int to,cap;
    double cost;
    int rev;
};

int V; // TODO:initialize
const int MAX_V = 666; // TODO:initialize
const double INF = 19191919; // TODO:initialize
vector<edge> G[MAX_V];
double h[MAX_V]; // ポテンシャル
double dist[MAX_V];
int prevv[MAX_V], preve[MAX_V]; // 直前の頂点と辺

void add_edge(int from, int to, int cap, double cost){
    G[from].pb({to,cap,cost,(int)G[to].size()});
    G[to].pb({from,0,-cost,(int)G[from].size()-1});
}

const double EPS = 1e-7;

// sからtへの流量fの最小費用流(不可能なら-1)
double min_cost_flow(int s, int t, int f){
    using pd = pair<double,int>;

    double res = 0;
    fill(h,h+V,0);
    while(f>0){
        priority_queue<pd,vector<pd>,greater<pd>> pq;
        fill(dist,dist+V,INF);
        dist[s]=0;
        // dijkstraでhを更新
        pq.push(pd(0,s));
        while(!pq.empty()){
            pd p = pq.top();
            pq.pop();
            int v = p.se;
            if(p.fi>dist[v]) continue;
            rep(i,G[v].size()){
                edge &e = G[v][i];
                if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to] + EPS){
                    dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    pq.push(pd(dist[e.to],e.to));
                }
            }
        }

        // これ以上流せない
        if( abs(dist[t]-INF) < EPS) return -1;

        rep(v,V) h[v] += dist[v];

        // s-t間の最短路に沿って目一杯流す
        int d=f;
        for(int v=t; v!=s; v=prevv[v]){
            // dbg(v);
            d = min(d,G[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d*h[t];

        for(int v=t; v!=s; v=prevv[v]){
            edge &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

using pi = pair<int,int>;

#define x first
#define y second

pi READ(){
    int x,y;
    cin >>x >>y;
    return {x,y};
}

double calc(pi p, pi q){
    double dx = p.x-q.x;
    double dy = p.y-q.y;
    return sqrt(dx*dx + dy*dy);
}

int main(){
    int n;
    cin >>n;

    pi start = READ();

    vector<pi> s(n),t(n);
    rep(i,n){
        s[i] = READ();
        t[i] = READ();
    }

    double ans = 0;
    rep(i,n) ans += calc(s[i], t[i]);

    set<pi> pts;
    map<pi,int> indeg,outdeg;
    rep(i,n){
        ++indeg[t[i]];
        ++outdeg[s[i]];
        pts.insert(s[i]);
        pts.insert(t[i]);
    }

    vector<pi> aa,bb;
    for(pi p:pts){
        int d = indeg[p] - outdeg[p];
        if(d==0) continue;

        if(d>0) aa.pb(p);
        else bb.pb(p);
    }
    sort(all(aa));
    aa.erase(unique(all(aa)), aa.end());
    sort(all(bb));
    bb.erase(unique(all(bb)), bb.end());

    int A = aa.size(), B = bb.size();
    int S = A+B, T = S+1;
    V = A+B+2;
    int f = 0;
    for(pi p:pts){
        int d = indeg[p] - outdeg[p];
        if(d==0) continue;

        if(d>0){
            int idx = lower_bound(all(aa), p) - aa.begin();
            add_edge(S,idx,d,0);
            f += d;
        }
        else{
            int idx = lower_bound(all(bb), p) - bb.begin();
            add_edge(A+idx,T,-d,0);
        }
    }
    rep(i,A)rep(j,B){
        add_edge(i,A+j,f,calc(aa[i],bb[j]));
    }

    ans += min_cost_flow(S,T,f);
    printf("%.15f\n", ans);
    return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 10184
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld = long double;
using point = complex<ld>;

const ld eps = 1e-10;
const ld INF = 1e9;

struct edge {
	int to, cap;
	ld cost;
	int rev;
	edge(int to_, int cap_, ld cost_, int rev_)
		: to(to_), cap(cap_), cost(cost_), rev(rev_) {}
};

const int MAX = 10000;

int V;

vector<edge> G[MAX];
ld h[MAX], dist[MAX];
int prevv[MAX], preve[MAX];

void add(int from, int to, int cap, ld cost) {
	G[from].emplace_back(to, cap, cost, G[to].size());
	G[to].emplace_back(from, 0, -cost, G[from].size() - 1);
}

ld calc(int s, int t, int f) {
	using pii = pair<ld, int>;
	ld res = 0;
	fill(h, h + V, 0);
	while (f > 0) {
		priority_queue<pii, vector<pii>, greater<pii>> que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.emplace(0, s);
		while (!que.empty()) {
			pii p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			for (size_t i = 0; i < G[v].size(); i++) {
				edge &e = G[v][i];
				if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to] + eps) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.emplace(dist[e.to], e.to);
				}
			}
		}
		assert(dist[t] < INF / 2);
		for (int v = 0; v < V; v++)
			h[v] += dist[v];
		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			edge &e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}
	return res;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	cout << fixed << setprecision(10);
	int n;
	cin >> n;
	int sx, sy;
	cin >> sx >> sy;
	point s(sx, sy);
	ld res = 0;
	vector<point> f(n), t(n);
	for (int i = 0; i < n; i++) {
		int x, y;
		cin >> x >> y;
		f[i] = point(x, y);
		cin >> x >> y;
		t[i] = point(x, y);
		res += abs(f[i] - t[i]);
	}
	V = n * 2 + 2;
	int src = n * 2, sink = n * 2 + 1;
	for (int i = 0; i < n; i++) {
		add(src, n + i, 1, 0);
		add(i, sink, 1, 0);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			add(n + i, j, 1, abs(t[i] - f[j]));
		}
	}
	res += calc(src, sink, n);
	cout << res << endl;
	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 15336
final_rank: 12

code_snippet: #include<bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1<<30
#define eps (1e-11)
#define MAX 700
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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);}

struct edge{ 
  int to,cap;
  double cost;
  int rev;
};

int v;
vector<edge> e[MAX];
double h[MAX];
double dist[MAX];
int prevv[MAX],preve[MAX];

void add_edge(int from,int to,int cap,double cost){
  e[from].push_back((edge){to,cap,cost,(int)e[to].size()});
  e[to].push_back((edge){from,0,-cost,(int)e[from].size()-1});
}

typedef pair<int,double> P;

double min_cost_flow(int s,int t,int f){
  double res=0.0;
  fill(h,h+v,0);
  while(f>0){
    priority_queue<P,vector<P>,greater<P> > pq;
    fill(dist,dist+v,inf);
    dist[s]=0;
    pq.push(P(0,s));
    while(pq.size()){
      P p=pq.top();
      pq.pop();
      int u=p.second;
      if(dist[u]-p.first<-eps)continue;
      for(int i=0;i<e[u].size();i++){
        edge &E=e[u][i];
        if(E.cap>0 && (dist[u]+E.cost+h[u]-h[E.to])-dist[E.to]<-eps){
          dist[E.to]=dist[u]+E.cost+h[u]-h[E.to];
          prevv[E.to]=u;
          preve[E.to]=i;
          pq.push(P(dist[E.to],E.to));
        }
      }
    }
    if(dist[t]==inf)return -1;
    for(int i=0;i<v;i++)h[i]+=dist[i];

    int d=f;
    for(int u=t;u!=s;u=prevv[u]){
      d=min(d,e[prevv[u]][preve[u]].cap);
    }
    f-=d;
    res+=(double)d*h[t];
    for(int u=t;u!=s;u=prevv[u]){
      edge &E=e[prevv[u]][preve[u]];
      E.cap-=d;
      e[u][E.rev].cap+=d;
    }
  }
  return res;
}

int main()
{
	int n;
	vector<Segment> vs,vt;
  vector<Point> ps;
	Point st;
	double ans=0.0;

  cin>>n;
  cin>>st.x>>st.y;
  for(int i=0;i<n;i++){
    Point a,b;
    cin>>a.x>>a.y>>b.x>>b.y;
    Segment s(a,b);
    vt.push_back(Segment(a,b));
    ans+=abs(b-a);
  }
  int s=vt.size()*2;
  int t=s+1;
  v=t+1;
  for(int i=0;i<vt.size();i++){
    for(int j=0;j<vt.size();j++){ 
      add_edge(i,j+vt.size(),1,abs(vt[i].p2-vt[j].p1));
    }
  }
  for(int i=0;i<vt.size();i++){
    add_edge(s,i,1,0);
    add_edge(i+vt.size(),t,1,0);
  }
  printf("%.10f\n",ans+min_cost_flow(s,t,vt.size()));
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 10240
final_rank: 6

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const 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;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* ??¢??¬??????????????? */
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 1500;
Weight h[V];                //??????????????£???
Weight dist[V];             //???????????¢
int prevv[V], preve[V];  //??´???????????¨??????


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]+eps) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	vector<pair<Point, Point>>pairs(N);
	for (int i = 0; i < N; ++i) {
		pairs[i] = make_pair(segs[i].a, segs[i].b);
	}

	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 12032
final_rank: 10

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

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    EACH(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
    REP(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
    REP(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}

typedef double Weight;

struct Edge {
    ll to, cap;
    Weight cost;
    ll rev;
};

vector< vector<Edge> > G;

void add_edge(ll from, ll to, ll cap, Weight cost) {
    if (from < 0 || to < 0) return;
    G[from].push_back({to, cap, cost, (ll)G[to].size()});
    G[to].push_back({from, 0, -cost, (ll)G[from].size()-1});
}

Weight dist[21000], h[21000] = {0};
ll prevV[21000], prevE[21000];
double min_cost_flow(ll s, ll t, ll f) {
    typedef pair<Weight, ll> _P;
    Weight res = 0;
    while (f > 0) {
        fill_n(dist, 21000, inf); dist[s] = 0;
        priority_queue<_P, vector<_P>, greater<_P> > Q; Q.push({0, s});
        while ( !Q.empty() ) {
            _P p = Q.top(); Q.pop();
            ll v = p.second;
            if (p.first > dist[v]) continue;
            REP(i, G[v].size()) {
                Edge& e = G[v][i];
                if (e.cap > 0 && dist[v]+e.cost+h[v]-h[e.to]+eps < dist[e.to]) {
                    dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
                    prevV[e.to] = v;
                    prevE[e.to] = i;
                    Q.push({dist[e.to], e.to});
                }
            }
        }
        REP(i, G.size()) h[i] += dist[i];

        if (abs(dist[t]-inf) < eps) {
            cout << "ERROR" << endl;
            exit(1);
        }

        ll d = f;
        for (ll v = t; v != s; v = prevV[v]) {
            d = min(d, G[prevV[v]][prevE[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for (ll v = t; v != s; v = prevV[v]) {
            Edge& e = G[prevV[v]][prevE[v]];
            e.cap -= d;
            G[e.to][e.rev].cap += d;
        }
    }
    return res;
}

typedef complex<double> Point;
template <typename T>
istream& operator>>(istream& is, complex<T>& p) {
    T x, y; is >> x >> y;
    p = {x, y};
    return is;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int n; cin >> n;
    Point sp; cin >> sp;
    vector<pair<Point,Point>> v(n);
    REP(i, n) cin >> v[i].first >> v[i].second;
    double ans = 0;
    REP(i, n) ans += abs(v[i].second-v[i].first);
    int lid = 0;
    vector<int> fid(n), tid(n);
    REP(i, n) fid[i] = lid++;
    REP(i, n) tid[i] = lid++;
    int s = lid++, t = lid++;
    G.clear(); G.resize(lid);
    REP(i, n) REP(j, n) {
        double cost = abs(v[i].second-v[j].first);
        add_edge(fid[i], tid[j], 1, cost);
    }
    REP(i, n) add_edge(s, fid[i], 1, 0);
    REP(i, n) add_edge(tid[i], t, 1, 0);
    ans += min_cost_flow(s, t, n);
    cout << fixed << setprecision(10) << ans << endl;
}
accuracy: 1
time_ms: 160
memory_kb: 12312
final_rank: 8

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

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    EACH(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
    REP(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
    REP(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}

typedef double Weight;

struct Edge {
    ll to, cap;
    Weight cost;
    ll rev;
};

vector< vector<Edge> > G;

void add_edge(ll from, ll to, ll cap, Weight cost) {
    if (from < 0 || to < 0) return;
    G[from].push_back({to, cap, cost, (ll)G[to].size()});
    G[to].push_back({from, 0, -cost, (ll)G[from].size()-1});
}

Weight dist[21000], h[21000] = {0};
ll prevV[21000], prevE[21000];
double min_cost_flow(ll s, ll t, ll f) {
    typedef pair<Weight, ll> _P;
    Weight res = 0;
    while (f > 0) {
        fill_n(dist, 21000, inf); dist[s] = 0;
        priority_queue<_P, vector<_P>, greater<_P> > Q; Q.push({0, s});
        while ( !Q.empty() ) {
            _P p = Q.top(); Q.pop();
            ll v = p.second;
            if (p.first > dist[v]) continue;
            REP(i, G[v].size()) {
                Edge& e = G[v][i];
                if (e.cap > eps && dist[v]+e.cost+h[v]-h[e.to]+eps < dist[e.to]) {
                    dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
                    prevV[e.to] = v;
                    prevE[e.to] = i;
                    Q.push({dist[e.to], e.to});
                }
            }
        }
        REP(i, G.size()) h[i] += dist[i];

        if (abs(dist[t]-inf) < eps) {
            cout << "ERROR" << endl;
            exit(1);
        }

        ll d = f;
        for (ll v = t; v != s; v = prevV[v]) {
            d = min(d, G[prevV[v]][prevE[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for (ll v = t; v != s; v = prevV[v]) {
            Edge& e = G[prevV[v]][prevE[v]];
            e.cap -= d;
            G[e.to][e.rev].cap += d;
        }
    }
    return res;
}

typedef complex<double> Point;
template <typename T>
istream& operator>>(istream& is, complex<T>& p) {
    T x, y; is >> x >> y;
    p = {x, y};
    return is;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int n; cin >> n;
    Point sp; cin >> sp;
    vector<pair<Point,Point>> v(n);
    REP(i, n) cin >> v[i].first >> v[i].second;
    double ans = 0;
    REP(i, n) ans += abs(v[i].second-v[i].first);
    int lid = 0;
    vector<int> fid(n), tid(n);
    REP(i, n) fid[i] = lid++;
    REP(i, n) tid[i] = lid++;
    int s = lid++, t = lid++;
    G.clear(); G.resize(lid);
    REP(i, n) REP(j, n) {
        double cost = abs(v[i].second-v[j].first);
        add_edge(fid[i], tid[j], 1, cost);
    }
    REP(i, n) add_edge(s, fid[i], 1, 0);
    REP(i, n) add_edge(tid[i], t, 1, 0);
    ans += min_cost_flow(s, t, n);
    cout << fixed << setprecision(10) << ans << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 12312
final_rank: 9

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* テ・ツケツセテ、ツスツ陛」ツ?ョテ・ツ淞コテヲツ慊ャ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// テァツつケテ」ツ?ョテ・ツ?・テ・ツ環?
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ティツェツ、テ・ツキツョテ」ツ?、テ」ツ?催ァツュツ嘉・ツ渉キテ・ツ按、テ・ツョツ?
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// テ・ツ??ァツゥツ?
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// テ・ツ、ツ姪ァツゥツ?
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// テァツ崢エテァツキツ堙」ツ?ョテ・ツョツ堙ァツセツゥ
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// テ・ツ??」ツ?ョテ・ツョツ堙ァツセツゥ
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
//-1: a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
// 2: c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
//-2: a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
// 0: a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (cross(nb, nc) < -eps) return -1; // a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (dot(nb, nc) < 0) return 2;       // c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	if (norm(nb) < norm(nc)) return -2;  // a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	return 0;                          // a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
}


/* テ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?*/

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ss(const Line& s, const 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;
}

// テァツつケテ」ツ?ョテァツ崢エテァツキツ堙、ツクツ甘・ツ按、テ・ツョツ?
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// テァツつケテ」ツ?ョテァツキツ堙・ツ按?、ツクツ甘・ツ按、テ・ツョツ?
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// テ・ツ楪づァツキツ堙」ツ?ョティツカツウ
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//テァツキツ堙・ツッツセティツアツ。テ」ツ?ョテ、ツスツ催ァツスツョテ」ツ?ォテ」ツ?づ」ツつ凝ァツつケ
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
//テ」ツ??ゥツ?催」ツ?ェテ」ツ?」テ」ツ?ヲテ」ツつ凝ゥツδィテ・ツ按?」ツ?づ」ツつ凝」ツ?ィassert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//テ・ツ?暗」ツ?ォisis_ssテ」ツ?療」ツ?ヲテ」ツ?ュ
		assert(false);
		return Point(0, 0);
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// テァツ崢エテァツキツ堙」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョティツキツ敕ゥツ崢「
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// テァツキツ堙・ツ按?」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ古ァツュツ嘉・ツ按?ァツキツ堙」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォ
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツ??・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツつ催・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:テ、ツクツヲティツ。ツ?
//c:テ、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉・ツ青古ィツキツ敕ゥツ崢「テ」ツ?ョテ、ツスツ催ァツスツョテ」ツつ津ヲツアツづ」ツつ?」ツつ凝」ツ??
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* テ・ツ??*/

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//テァツつケテ」ツ?古・ツ??」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//テ・ツ??cテ」ツ?古・ツ??cテ」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// テ・ツ??」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// テ・ツ??」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// テ・ツ??」ツ?ィテァツつケテ」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//テ、ツコツ古」ツ?、テ」ツ?ョテ・ツ??」ツ?ョテゥツ?催」ツ?ェテ」ツつ甘ゥツ敖「テァツゥツ?
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* テ・ツ、ツ堙ィツァツ津・ツスツ「 */

typedef vector<Point> Polygon;

// テゥツ敖「テァツゥツ?
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//テ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテ・ツ崢榲ィツサツ「テヲツ鳴ケテ・ツ青?
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?テ」ツ??ゥツォツ佚ゥツ??
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// テ・ツ?クテ・ツ個?
//テァツつケテ」ツつ?ァツキツ堙」ツつ津ィツソツ氾」ツ?凖」ツ?禿」ツ?ィテ」ツつづヲツ慊嘉」ツつ甘・ツセツ療」ツつ凝」ツ?ョテ」ツ?ァテヲツウツィテヲツ??
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//テ・ツ?クテ」ツつォテ」ツδε」ツδ?
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* テ」ツつ「テ」ツδャテ」ツδウテ」ツつクテ」ツδ。テ」ツδウテ」ツδ?*/
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 1000;
Weight h[V];                //テ」ツδ敕」ツδ?」ツδウテ」ツつキテ」ツδ」テ」ツδォ
Weight dist[V];             //テヲツ慊?ァツ淞ュティツキツ敕ゥツ崢「
int prevv[V], preve[V];  //テァツ崢エテ・ツ可催」ツ?ョティツセツコテ」ツ?ィテゥツ?づァツつケ


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	auto p= sennbunn_arrangement(segs);
	vector<Point>ps(p.first);
	Graph ori = p.second;
	
	vector<pair<Point, Point>>pairs;
	for (Edges& es : ori) {
		for ( Edge& e : es) {
			const int src = e.src;
			const int dst = e.dest;
			for (int i = 0; i < N; ++i) {
				if (isis_lp(segs[i], ps[src]) && isis_lp(segs[i], ps[dst])) {
					if (abs(ps[dst] - segs[i].a)>abs(ps[src] - segs[i].a)) {
						pairs.push_back(make_pair(ps[src], ps[dst]));
					}
					break;
				}
			}
		}
	}
	sort(pairs.begin(), pairs.end());
	pairs.erase(unique(pairs.begin(), pairs.end()), pairs.end());
	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			if (i == j)continue;
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 0.07272727272727272
time_ms: 50
memory_kb: 32480
final_rank: 20

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const 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;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* ??¢??¬??????????????? */
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 1000;
Weight h[V];                //??????????????£???
Weight dist[V];             //???????????¢
int prevv[V], preve[V];  //??´???????????¨??????


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	auto p= sennbunn_arrangement(segs);
	vector<Point>ps(p.first);
	Graph ori = p.second;
	
	vector<pair<Point, Point>>pairs;
	for (Edges& es : ori) {
		for ( Edge& e : es) {
			const int src = e.src;
			const int dst = e.dest;
			for (int i = 0; i < N; ++i) {
				if (isis_lp(segs[i], ps[src]) && isis_lp(segs[i], ps[dst])) {
					if (abs(ps[dst] - segs[i].a)>abs(ps[src] - segs[i].a)) {
						pairs.push_back(make_pair(ps[src], ps[dst]));
					}
					break;
				}
			}
		}
	}
	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			if (i == j)continue;
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 0.07272727272727272
time_ms: 40
memory_kb: 32552
final_rank: 18

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* テ・ツケツセテ、ツスツ陛」ツ?ョテ・ツ淞コテヲツ慊ャ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// テァツつケテ」ツ?ョテ・ツ?・テ・ツ環?
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ティツェツ、テ・ツキツョテ」ツ?、テ」ツ?催ァツュツ嘉・ツ渉キテ・ツ按、テ・ツョツ?
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// テ・ツ??ァツゥツ?
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// テ・ツ、ツ姪ァツゥツ?
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// テァツ崢エテァツキツ堙」ツ?ョテ・ツョツ堙ァツセツゥ
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// テ・ツ??」ツ?ョテ・ツョツ堙ァツセツゥ
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
//-1: a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
// 2: c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
//-2: a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
// 0: a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (cross(nb, nc) < -eps) return -1; // a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (dot(nb, nc) < 0) return 2;       // c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	if (norm(nb) < norm(nc)) return -2;  // a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	return 0;                          // a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
}


/* テ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?*/

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ss(const Line& s, const 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;
}

// テァツつケテ」ツ?ョテァツ崢エテァツキツ堙、ツクツ甘・ツ按、テ・ツョツ?
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// テァツつケテ」ツ?ョテァツキツ堙・ツ按?、ツクツ甘・ツ按、テ・ツョツ?
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// テ・ツ楪づァツキツ堙」ツ?ョティツカツウ
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//テァツキツ堙・ツッツセティツアツ。テ」ツ?ョテ、ツスツ催ァツスツョテ」ツ?ォテ」ツ?づ」ツつ凝ァツつケ
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
//テ」ツ??ゥツ?催」ツ?ェテ」ツ?」テ」ツ?ヲテ」ツつ凝ゥツδィテ・ツ按?」ツ?づ」ツつ凝」ツ?ィassert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//テ・ツ?暗」ツ?ォisis_ssテ」ツ?療」ツ?ヲテ」ツ?ュ
		assert(false);
		return Point(0, 0);
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// テァツ崢エテァツキツ堙」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョティツキツ敕ゥツ崢「
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// テァツキツ堙・ツ按?」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ古ァツュツ嘉・ツ按?ァツキツ堙」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォ
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツ??・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツつ催・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:テ、ツクツヲティツ。ツ?
//c:テ、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉・ツ青古ィツキツ敕ゥツ崢「テ」ツ?ョテ、ツスツ催ァツスツョテ」ツつ津ヲツアツづ」ツつ?」ツつ凝」ツ??
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* テ・ツ??*/

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//テァツつケテ」ツ?古・ツ??」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//テ・ツ??cテ」ツ?古・ツ??cテ」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// テ・ツ??」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// テ・ツ??」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// テ・ツ??」ツ?ィテァツつケテ」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//テ、ツコツ古」ツ?、テ」ツ?ョテ・ツ??」ツ?ョテゥツ?催」ツ?ェテ」ツつ甘ゥツ敖「テァツゥツ?
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* テ・ツ、ツ堙ィツァツ津・ツスツ「 */

typedef vector<Point> Polygon;

// テゥツ敖「テァツゥツ?
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//テ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテ・ツ崢榲ィツサツ「テヲツ鳴ケテ・ツ青?
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?テ」ツ??ゥツォツ佚ゥツ??
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// テ・ツ?クテ・ツ個?
//テァツつケテ」ツつ?ァツキツ堙」ツつ津ィツソツ氾」ツ?凖」ツ?禿」ツ?ィテ」ツつづヲツ慊嘉」ツつ甘・ツセツ療」ツつ凝」ツ?ョテ」ツ?ァテヲツウツィテヲツ??
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//テ・ツ?クテ」ツつォテ」ツδε」ツδ?
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* テ」ツつ「テ」ツδャテ」ツδウテ」ツつクテ」ツδ。テ」ツδウテ」ツδ?*/
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 1000;
Weight h[V];                //テ」ツδ敕」ツδ?」ツδウテ」ツつキテ」ツδ」テ」ツδォ
Weight dist[V];             //テヲツ慊?ァツ淞ュティツキツ敕ゥツ崢「
int prevv[V], preve[V];  //テァツ崢エテ・ツ可催」ツ?ョティツセツコテ」ツ?ィテゥツ?づァツつケ


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	auto p= sennbunn_arrangement(segs);
	vector<Point>ps(p.first);
	Graph ori = p.second;
	
	vector<pair<Point, Point>>pairs;
	for (Edges& es : ori) {
		for ( Edge& e : es) {
			const int src = e.src;
			const int dst = e.dest;
			for (int i = 0; i < N; ++i) {
				if (isis_lp(segs[i], ps[src]) && isis_lp(segs[i], ps[dst])) {
					if (abs(ps[dst] - segs[i].a)>abs(ps[src] - segs[i].a)) {
						pairs.push_back(make_pair(ps[src], ps[dst]));
					}
					break;
				}
			}
		}
	}
	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			if (i == j)continue;
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 0.07272727272727272
time_ms: 30
memory_kb: 32444
final_rank: 16

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* テ・ツケツセテ、ツスツ陛」ツ?ョテ・ツ淞コテヲツ慊ャ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// テァツつケテ」ツ?ョテ・ツ?・テ・ツ環?
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ティツェツ、テ・ツキツョテ」ツ?、テ」ツ?催ァツュツ嘉・ツ渉キテ・ツ按、テ・ツョツ?
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// テ・ツ??ァツゥツ?
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// テ・ツ、ツ姪ァツゥツ?
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// テァツ崢エテァツキツ堙」ツ?ョテ・ツョツ堙ァツセツゥ
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// テ・ツ??」ツ?ョテ・ツョツ堙ァツセツゥ
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
//-1: a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
// 2: c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
//-2: a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
// 0: a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,cテ」ツ?古・ツ渉催ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (cross(nb, nc) < -eps) return -1; // a,b,cテ」ツ?古ヲツ卍づィツィツ暗・ツ堕ィテ」ツつ甘」ツ?ョテゥツ??」ツ?ォテ、ツクツヲテ」ツ?カ
	if (dot(nb, nc) < 0) return 2;       // c,a,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	if (norm(nb) < norm(nc)) return -2;  // a,b,cテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
	return 0;                          // a,c,bテ」ツ?ョテゥツ??」ツ?ォテァツ崢エテァツキツ堙」ツ?ォテ、ツクツヲテ」ツ?カ
}


/* テ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?*/

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool isis_ss(const Line& s, const 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;
}

// テァツつケテ」ツ?ョテァツ崢エテァツキツ堙、ツクツ甘・ツ按、テ・ツョツ?
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// テァツつケテ」ツ?ョテァツキツ堙・ツ按?、ツクツ甘・ツ按、テ・ツョツ?
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// テ・ツ楪づァツキツ堙」ツ?ョティツカツウ
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//テァツキツ堙・ツッツセティツアツ。テ」ツ?ョテ、ツスツ催ァツスツョテ」ツ?ォテ」ツ?づ」ツつ凝ァツつケ
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
//テ」ツ??ゥツ?催」ツ?ェテ」ツ?」テ」ツ?ヲテ」ツつ凝ゥツδィテ・ツ按?」ツ?づ」ツつ凝」ツ?ィassert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//テ・ツ?暗」ツ?ォisis_ssテ」ツ?療」ツ?ヲテ」ツ?ュ
		assert(false);
		return Point(0, 0);
	}
}
// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// テァツ崢エテァツキツ堙」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョティツキツ敕ゥツ崢「
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// テァツ崢エテァツキツ堙」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// テァツキツ堙・ツ按?」ツ?ィテァツつケテ」ツ?ョティツキツ敕ゥツ崢「
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// テァツキツ堙・ツ按?」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//テァツ崢エテァツキツ堙」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ古ァツュツ嘉・ツ按?ァツキツ堙」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォ
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツ??・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉」ツ?ェテ」ツつ凝・ツつ催・ツソツ?
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?古、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??」ツ?禿」ツ?ィテ」ツ?ッテァツ「ツコテ」ツ?凝」ツつ?」ツ?ィテ」ツ??」ツ?ヲテ」ツ?ュ
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:テ、ツクツヲティツ。ツ?
//c:テ、ツクツヲティツ。ツ古」ツ?ァテ」ツ?ェテ」ツ??
//テ、ツクツ嘉」ツ?、テ」ツ?ョテァツ崢エテァツキツ堙」ツ?凝」ツつ嘉・ツ青古ィツキツ敕ゥツ崢「テ」ツ?ョテ、ツスツ催ァツスツョテ」ツつ津ヲツアツづ」ツつ?」ツつ凝」ツ??
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* テ・ツ??*/

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//テァツつケテ」ツ?古・ツ??」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//テ・ツ??cテ」ツ?古・ツ??cテ」ツ?ョテ、ツクツュテ」ツ?ォテ」ツ??」ツつ凝」ツ??
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// テ・ツ??」ツ?ィテァツ崢エテァツキツ堙」ツ?ョテ、ツコツ、テァツつケ
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// テ・ツ??」ツ?ィテァツキツ堙・ツ按?」ツ?ョティツキツ敕ゥツ崢「
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// テ・ツ??」ツ?ィテァツつケテ」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテヲツ篠・テァツキツ?
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//テ、ツコツ古」ツ?、テ」ツ?ョテ・ツ??」ツ?ョテゥツ?催」ツ?ェテ」ツつ甘ゥツ敖「テァツゥツ?
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* テ・ツ、ツ堙ィツァツ津・ツスツ「 */

typedef vector<Point> Polygon;

// テゥツ敖「テァツゥツ?
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//テ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテ・ツ崢榲ィツサツ「テヲツ鳴ケテ・ツ青?
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//テ・ツ??」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?テ」ツ??ゥツォツ佚ゥツ??
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// テ・ツ?クテ・ツ個?
//テァツつケテ」ツつ?ァツキツ堙」ツつ津ィツソツ氾」ツ?凖」ツ?禿」ツ?ィテ」ツつづヲツ慊嘉」ツつ甘・ツセツ療」ツつ凝」ツ?ョテ」ツ?ァテヲツウツィテヲツ??
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//テ・ツ?クテ」ツつォテ」ツδε」ツδ?
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* テ」ツつ「テ」ツδャテ」ツδウテ」ツつクテ」ツδ。テ」ツδウテ」ツδ?*/
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 400;
Weight h[V];                //テ」ツδ敕」ツδ?」ツδウテ」ツつキテ」ツδ」テ」ツδォ
Weight dist[V];             //テヲツ慊?ァツ淞ュティツキツ敕ゥツ崢「
int prevv[V], preve[V];  //テァツ崢エテ・ツ可催」ツ?ョティツセツコテ」ツ?ィテゥツ?づァツつケ


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	auto p= sennbunn_arrangement(segs);
	vector<Point>ps(p.first);
	Graph ori = p.second;
	
	vector<pair<Point, Point>>pairs;
	for (Edges& es : ori) {
		for ( Edge& e : es) {
			const int src = e.src;
			const int dst = e.dest;
			for (int i = 0; i < N; ++i) {
				if (isis_lp(segs[i], ps[src]) && isis_lp(segs[i], ps[dst])) {
					if (abs(ps[dst] - segs[i].a)>abs(ps[src] - segs[i].a)) {
						pairs.push_back(make_pair(ps[src], ps[dst]));
					}
					break;
				}
			}
		}
	}
	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			if (i == j)continue;
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 0.07272727272727272
time_ms: 50
memory_kb: 32356
final_rank: 19

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const 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;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* ??¢??¬??????????????? */
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}




typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, int cap, Weight weight) {
	g[src].push_back(Edge{ src, dest, cap, (int)g[dest].size(), weight });
	g[dest].push_back(Edge{ dest, src, 0, (int)g[src].size() - 1, -weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) {
			if (isis_sp(s[i], p[j]))
				vec.emplace_back(abs(s[i].a - p[j]), j);
		}
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, 1,static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	return g;
}
pair<vector<Point>,Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	
	return make_pair(crss,segment_arrangement(s, crss));
}

Graph Circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	const int n = p.size(), m = c.size();
	Graph g(n);
	rep(i, m) {
		vector<pair<ld, int>> vec;
		rep(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(all(vec));
		rep(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, 1,static_cast<Weight>(angle * c[i].r));
		}
	}
	return g;
}

const int V = 400;
Weight h[V];                //??????????????£???
Weight dist[V];             //???????????¢
int prevv[V], preve[V];  //??´???????????¨??????


#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const Weight INF =1e18;
Weight min_cost_flow(Graph &g, int s, int t, int f) {
	Weight res = 0;
	memset(h, 0, sizeof(h));
	typedef pair<Weight, int> P;
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P> > que;
		fill(dist, dist + V, INF);
		dist[s] = 0;
		que.push(P(0, s));
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first) continue;
			REP(i, g[v].size()) {
				Edge &e = g[v][i];
				if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest]) {
					dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest];
					prevv[e.dest] = v;
					preve[e.dest] = i;
					que.push(P(dist[e.dest], e.dest));
				}
			}
		}
		if (dist[t] == INF) return -1;
		REP(v, V) h[v] =h[v]+ dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
		f -= d;
		res = res+d * h[t];
		for (int v = t; v != s; v = prevv[v]) {
			Edge &e = g[prevv[v]][preve[v]];
			e.cap -= d;
			g[v][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N; cin >> N;
	ld sx, sy; cin >> sx >> sy;
	Point sp;
	sp = Point(sx, sy);
	vector<Line>segs(N);
	ld aans = 0;
	for (int i = 0; i < N; ++i) {
		ld ax, ay, bx, by; cin >> ax >> ay >> bx >> by;
		segs[i] = Line(Point(ax, ay), Point(bx, by));
		aans += abs(segs[i].b - segs[i].a);
	}
	auto p= sennbunn_arrangement(segs);
	vector<Point>ps(p.first);
	Graph ori = p.second;
	
	vector<pair<Point, Point>>pairs;
	for (Edges& es : ori) {
		for ( Edge& e : es) {
			const int src = e.src;
			const int dst = e.dest;
			for (int i = 0; i < N; ++i) {
				if (isis_lp(segs[i], ps[src]) && isis_lp(segs[i], ps[dst])) {
					if (abs(ps[dst] - segs[i].a)>abs(ps[src] - segs[i].a)) {
						pairs.push_back(make_pair(ps[src], ps[dst]));
					}
					break;
				}
			}
		}
	}
	const int start = 0;
	const int in = start + 1;
	const int out = in + pairs.size();
	const int goal = out + pairs.size();
	Graph aft(goal + 1);
	for (int i = 0; i < pairs.size(); ++i) {
		for (int j = 0; j < pairs.size(); ++j) {
			if (i == j)continue;
			ld dis= abs(pairs[i].second - pairs[j].first);
			add_edge(aft, in + i, out + j, 1, dis);
		}
	}
	for (int i = 0; i < pairs.size(); ++i) {
		
		add_edge(aft, start, in+i, 1, 0);
		add_edge(aft, out+i, goal, 1, 0);
		
	}
	aans=aans+ min_cost_flow(aft, start, goal, pairs.size());
	cout << fixed<<setprecision(22)<<aans << endl;
	return 0;
}
accuracy: 0.07272727272727272
time_ms: 40
memory_kb: 32516
final_rank: 17

code_snippet: #include<bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1<<30
#define eps (1e-11)
#define MAX 700
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):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);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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);}

struct edge{ 
  int to,cap;
  double cost;
  int rev;
};

int v;
vector<edge> e[MAX];
double h[MAX];
double dist[MAX];
int prevv[MAX],preve[MAX];

void add_edge(int from,int to,int cap,double cost){
  e[from].push_back((edge){to,cap,cost,(int)e[to].size()});
  e[to].push_back((edge){from,0,-cost,(int)e[from].size()-1});
}

typedef pair<int,double> P;

double min_cost_flow(int s,int t,int f){
  double res=0.0;
  fill(h,h+v,0);
  while(f>0){
    priority_queue<P,vector<P>,greater<P> > pq;
    fill(dist,dist+v,inf);
    dist[s]=0;
    pq.push(P(0,s));
    while(pq.size()){
      P p=pq.top();
      pq.pop();
      int u=p.second;
      if(dist[u]-p.first<-eps)continue;
      for(int i=0;i<e[u].size();i++){
        edge &E=e[u][i];
        if(E.cap>0 && (dist[u]+E.cost+h[u]-h[E.to])-dist[E.to]<-eps){
          dist[E.to]=dist[u]+E.cost+h[u]-h[E.to];
          prevv[E.to]=u;
          preve[E.to]=i;
          pq.push(P(dist[E.to],E.to));
        }
      }
    }
    if(dist[t]==inf)return -1;
    for(int i=0;i<v;i++)h[i]+=dist[i];

    int d=f;
    for(int u=t;u!=s;u=prevv[u]){
      d=min(d,e[prevv[u]][preve[u]].cap);
    }
    f-=d;
    res+=(double)d*h[t];
    for(int u=t;u!=s;u=prevv[u]){
      edge &E=e[prevv[u]][preve[u]];
      E.cap-=d;
      e[u][E.rev].cap+=d;
    }
  }
  return res;
}

int main()
{
  int n;
  vector<Segment> vs,vt;
  Point st;
  double ans=0.0;

  cin>>n;
  cin>>st.x>>st.y;
  for(int i=0;i<n;i++){
    Point a,b;
    cin>>a.x>>a.y>>b.x>>b.y;
    Segment s(a,b);
     vt.push_back(Segment(a,b));
    ans+=abs(b-a);
  }

  int s=vt.size()*2;
  int t=s+1;
  v=t+1;
  for(int i=0;i<vt.size();i++){
    for(int j=0;j<vt.size();j++){ 
      add_edge(i,j+vt.size(),1,abs(vt[i].p2-vt[j].p1));
    }
  }
  for(int i=0;i<vt.size();i++){
    add_edge(s,i,1,0);
    add_edge(i+vt.size(),t,1,0);
  }
  printf("%.10f\n",ans+min_cost_flow(s,t,vt.size()));
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 8496
final_rank: 4