## 1. Abridged problem statement

We are given `N ≤ 300` border segments of a planar subdivision of Berland into polygonal provinces. Each segment has a positive building cost `v`. Two headquarters points lie strictly inside two different provinces.

We must build a wall only along given border segments. The wall must be a simple polygon and must separate the two headquarters, i.e. exactly one headquarters must lie inside the polygon. Find a minimum-total-cost set/sequence of segments forming such a wall, and output its cost and segment indices.

---

## 2. Detailed editorial

### Graph interpretation

The province borders form a planar graph:

- segment endpoints are graph vertices,
- border segments are graph edges,
- edge weights are the given costs.

Because segments do not properly intersect — they can only meet at common endpoints — any simple cycle in this graph corresponds to a simple polygonal wall.

So the task becomes:

> Find a minimum-cost simple cycle in the planar graph such that the two given points lie on different sides of that cycle.

---

### Separating two points using ray parity

For a simple polygon, a point is inside it iff a ray from the point crosses the polygon boundary an odd number of times.

Take an upward vertical ray from each headquarters.

For every graph edge/segment `e`, define:

```text
c1(e) = 1 if e crosses the upward ray from headquarters 1, else 0
c2(e) = 1 if e crosses the upward ray from headquarters 2, else 0
```

For a cycle `C`:

```text
point 1 is inside C iff XOR of c1(e) over e in C is 1
point 2 is inside C iff XOR of c2(e) over e in C is 1
```

The wall separates the two headquarters iff exactly one of these parities is odd:

```text
(XOR c1(e)) != (XOR c2(e))
```

Equivalently:

```text
XOR over e in C of (c1(e) XOR c2(e)) = 1
```

So assign each graph edge a binary label:

```text
parity(e) = c1(e) XOR c2(e)
```

Now the problem is:

> Find a minimum-cost cycle whose XOR of edge parity labels is `1`.

---

### Minimum odd-parity cycle via doubled-state Dijkstra

We create a doubled graph of states:

```text
(vertex, accumulated_parity)
```

There are `2 * V` states.

For every original edge `u -- v` with cost `w` and parity `p`, add transitions:

```text
(u, q) -> (v, q XOR p)
(v, q) -> (u, q XOR p)
```

for both `q = 0, 1`.

Now, a path in this doubled graph from:

```text
(s, 0) to (s, 1)
```

corresponds to a closed walk in the original graph starting and ending at `s`, with odd total edge parity.

So for each possible starting vertex `s`, we run Dijkstra from `(s, 0)` and look at the distance to `(s, 1)`.

The minimum over all `s` is the desired answer.

---

### Why this gives a simple cycle

Dijkstra gives a minimum-cost odd-parity closed walk. A closed walk may repeat vertices/edges, but since all edge costs are positive, any useless even-parity subcycle can be removed. The remaining minimum odd-parity closed walk contains at least one odd-parity simple cycle, with cost no larger.

Therefore, minimizing over closed walks is enough to find the optimal simple polygonal wall.

---

### Complexity

Let:

- `V` be the number of distinct endpoints, `V ≤ 2N`,
- `E = N`.

For each vertex, we run Dijkstra on `2V` states and `2E` transitions.

Complexity:

```text
O(V * E log V)
```

Since `N ≤ 300`, this easily fits.

---

## 3. Provided C++ solution with detailed comments

```cpp
#include <bits/stdc++.h> // Includes almost all standard C++ headers.

using namespace std;

// Convenience output operator for pairs.
template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

// Convenience input operator for pairs.
template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

// Convenience input operator for vectors.
template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

// Convenience output operator for vectors.
// Prints elements separated by spaces.
template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

// Coordinate type used by the geometry helper.
using coord_t = double;

// Basic 2D point/vector structure.
// Many methods here are not needed by the final algorithm,
// but they are part of the provided solution template.
struct Point {
    // Small epsilon for floating-point comparisons.
    static constexpr coord_t eps = 1e-9;

    // Pi constant.
    static inline const coord_t PI = acos((coord_t)-1.0);

    // Point coordinates.
    coord_t x, y;

    // Constructor, defaulting to the origin.
    Point(coord_t x = 0, coord_t y = 0) : x(x), y(y) {}

    // Vector addition.
    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }

    // Vector subtraction.
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }

    // Multiplication by scalar.
    Point operator*(coord_t c) const { return Point(x * c, y * c); }

    // Division by scalar.
    Point operator/(coord_t c) const { return Point(x / c, y / c); }

    // Dot product.
    coord_t operator*(const Point& p) const { return x * p.x + y * p.y; }

    // Cross product.
    coord_t operator^(const Point& p) const { return x * p.y - y * p.x; }

    // Exact equality; okay here because input coordinates are integers.
    bool operator==(const Point& p) const { return x == p.x && y == p.y; }

    // Exact inequality.
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }

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

    // Reverse lexicographic comparison.
    bool operator>(const Point& p) const {
        return x != p.x ? x > p.x : y > p.y;
    }

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

    // Lexicographic >= comparison.
    bool operator>=(const Point& p) const {
        return x != p.x ? x > p.x : y >= p.y;
    }

    // Squared Euclidean norm.
    coord_t norm2() const { return x * x + y * y; }

    // Euclidean norm.
    coord_t norm() const { return sqrt(norm2()); }

    // Polar angle.
    coord_t angle() const { return atan2(y, x); }

    // Rotate point/vector by angle a.
    Point rotate(coord_t a) const {
        return Point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }

    // Perpendicular vector.
    Point perp() const { return Point(-y, x); }

    // Unit vector in same direction.
    Point unit() const { return *this / norm(); }

    // Unit normal vector.
    Point normal() const { return perp().unit(); }

    // Projection of vector p onto this vector.
    Point project(const Point& p) const {
        return *this * (*this * p) / norm2();
    }

    // Reflection of vector p around this vector.
    Point reflect(const Point& p) const {
        return *this * 2 * (*this * p) / norm2() - p;
    }

    // Output point.
    friend ostream& operator<<(ostream& os, const Point& p) {
        return os << p.x << ' ' << p.y;
    }

    // Input point.
    friend istream& operator>>(istream& is, Point& p) {
        return is >> p.x >> p.y;
    }

    // Orientation test:
    // returns 1 if a,b,c make a counterclockwise turn,
    // -1 if clockwise,
    // 0 if collinear.
    friend int ccw(const Point& a, const Point& b, const Point& c) {
        coord_t v = (b - a) ^ (c - a);
        if(-eps <= v && v <= eps) {
            return 0;
        } else if(v > 0) {
            return 1;
        } else {
            return -1;
        }
    }

    // Checks whether p lies on segment ab.
    friend bool point_on_segment(
        const Point& a, const Point& b, const Point& p
    ) {
        return ccw(a, b, p) == 0 && p.x >= min(a.x, b.x) - eps &&
               p.x <= max(a.x, b.x) + eps && p.y >= min(a.y, b.y) - eps &&
               p.y <= max(a.y, b.y) + eps;
    }

    // Checks whether p lies inside or on triangle abc.
    friend bool point_in_triangle(
        const Point& a, const Point& b, const Point& c, const Point& p
    ) {
        int d1 = ccw(a, b, p);
        int d2 = ccw(b, c, p);
        int d3 = ccw(c, a, p);
        return (d1 >= 0 && d2 >= 0 && d3 >= 0) ||
               (d1 <= 0 && d2 <= 0 && d3 <= 0);
    }

    // Intersection point of two non-parallel lines a1b1 and a2b2.
    friend Point line_line_intersection(
        const Point& a1, const Point& b1, const Point& a2, const Point& b2
    ) {
        return a1 +
               (b1 - a1) * ((a2 - a1) ^ (b2 - a2)) / ((b1 - a1) ^ (b2 - a2));
    }

    // Checks if vectors a and b are collinear.
    friend bool collinear(const Point& a, const Point& b) {
        return abs(a ^ b) < eps;
    }

    // Circumcenter of triangle abc.
    friend Point circumcenter(const Point& a, const Point& b, const Point& c) {
        Point mid_ab = (a + b) / 2.0;
        Point mid_ac = (a + c) / 2.0;
        Point perp_ab = (b - a).perp();
        Point perp_ac = (c - a).perp();
        return line_line_intersection(
            mid_ab, mid_ab + perp_ab, mid_ac, mid_ac + perp_ac
        );
    }

    // Signed area contribution of a circular arc.
    friend coord_t arc_area(
        const Point& center, coord_t r, const Point& p1, const Point& p2
    ) {
        coord_t theta1 = (p1 - center).angle();
        coord_t theta2 = (p2 - center).angle();
        if(theta2 < theta1 - eps) {
            theta2 += 2 * PI;
        }

        coord_t d_theta = theta2 - theta1;
        coord_t cx = center.x, cy = center.y;
        coord_t area = r * cx * (sin(theta2) - sin(theta1)) -
                       r * cy * (cos(theta2) - cos(theta1)) + r * r * d_theta;
        return area / 2.0;
    }

    // Intersection points of two circles.
    friend vector<Point> intersect_circles(
        const Point& c1, coord_t r1, const Point& c2, coord_t r2
    ) {
        Point d = c2 - c1;
        coord_t dist = d.norm();

        if(dist > r1 + r2 + eps || dist < abs(r1 - r2) - eps || dist < eps) {
            return {};
        }

        coord_t a = (r1 * r1 - r2 * r2 + dist * dist) / (2 * dist);
        coord_t h_sq = r1 * r1 - a * a;
        if(h_sq < -eps) {
            return {};
        }
        if(h_sq < 0) {
            h_sq = 0;
        }
        coord_t h = sqrt(h_sq);

        Point mid = c1 + d.unit() * a;
        Point perp_dir = d.perp().unit();

        if(h < eps) {
            return {mid};
        }
        return {mid + perp_dir * h, mid - perp_dir * h};
    }

    // Intersection between a ray and a segment.
    friend optional<Point> intersect_ray_segment(
        const Point& ray_start, const Point& ray_through, const Point& seg_a,
        const Point& seg_b
    ) {
        Point ray_dir = ray_through - ray_start;
        if(ray_dir.norm2() < Point::eps) {
            return {};
        }
        Point seg_dir = seg_b - seg_a;
        coord_t denom = ray_dir ^ seg_dir;
        if(fabs(denom) < eps) {
            return {};
        }
        coord_t t = ((seg_a - ray_start) ^ seg_dir) / denom;
        if(t < eps) {
            return {};
        }
        coord_t s = ((seg_a - ray_start) ^ ray_dir) / denom;
        if(s < eps || s > 1 - eps) {
            return {};
        }
        return ray_start + ray_dir * t;
    }
};

// Number of given border segments.
int n;

// Segment endpoints.
vector<Point> seg_a, seg_b;

// Segment costs.
vector<int> seg_v;

// Headquarters coordinates.
Point hq1, hq2;

// Reads input.
void read() {
    cin >> n;

    seg_a.resize(n);
    seg_b.resize(n);
    seg_v.resize(n);

    for(int i = 0; i < n; i++) {
        cin >> seg_a[i] >> seg_b[i] >> seg_v[i];
    }

    cin >> hq1 >> hq2;
}

void solve() {
    // Map from integer endpoint coordinates to compact vertex id.
    map<pair<long long, long long>, int> idx;

    // Returns id of point p, creating it if needed.
    auto get_idx = [&](const Point& p) -> int {
        // Coordinates are integers in the input; round double to long long.
        pair<long long, long long> key = {llround(p.x), llround(p.y)};

        auto it = idx.find(key);

        // Existing vertex.
        if(it != idx.end()) {
            return it->second;
        }

        // New vertex id.
        int id = idx.size();
        idx[key] = id;
        return id;
    };

    // Checks whether segment ab crosses the upward vertical ray from h.
    auto crosses_up_ray = [&](const Point& a, const Point& b,
                              const Point& h) -> bool {
        // Compare endpoints with the vertical line x = h.x.
        bool sa = a.x > h.x, sb = b.x > h.x;

        // If both endpoints are on the same side, no proper crossing.
        if(sa == sb) {
            return false;
        }

        // Compute parameter t where the segment intersects x = h.x.
        coord_t t = (h.x - a.x) / (b.x - a.x);

        // Compute y-coordinate of that intersection point.
        coord_t y_at_cross = a.y + t * (b.y - a.y);

        // It crosses the upward ray only if intersection is above h.
        return y_at_cross > h.y;
    };

    int m = 0; // Number of graph vertices.

    // eu[i], ev[i] are endpoint vertex ids of segment i.
    // epar[i] is the parity label of segment i.
    vector<int> eu(n), ev(n), epar(n);

    for(int i = 0; i < n; i++) {
        // Convert segment endpoints to graph vertices.
        eu[i] = get_idx(seg_a[i]);
        ev[i] = get_idx(seg_b[i]);

        // Whether segment crosses upward ray from each headquarters.
        int c1 = crosses_up_ray(seg_a[i], seg_b[i], hq1);
        int c2 = crosses_up_ray(seg_a[i], seg_b[i], hq2);

        // Edge parity is 1 iff it changes relative inside/outside parity.
        epar[i] = c1 ^ c2;

        // Update number of vertices.
        m = max({m, eu[i] + 1, ev[i] + 1});
    }

    // Adjacency list:
    // for each vertex, store tuples (neighbor, cost, segment_index).
    vector<vector<tuple<int, int, int>>> adj(m);

    for(int i = 0; i < n; i++) {
        // Undirected edge.
        adj[eu[i]].push_back({ev[i], seg_v[i], i});
        adj[ev[i]].push_back({eu[i], seg_v[i], i});
    }

    // Infinite distance.
    const long long inf = numeric_limits<long long>::max();

    // Dijkstra on doubled parity graph.
    auto dijkstra = [&](int src, vector<long long>& dist,
                        vector<pair<int, int>>& par) {
        // There are 2 states per vertex:
        // state 2*v + p means vertex v with accumulated parity p.
        dist.assign(2 * m, inf);

        // Parent array for path reconstruction:
        // par[state] = {previous_state, segment_used_to_get_here}.
        par.assign(2 * m, {-1, -1});

        // Min-priority queue of (distance, state).
        priority_queue<
            pair<long long, int>, vector<pair<long long, int>>,
            greater<pair<long long, int>>>
            pq;

        // Source state has distance 0.
        dist[src] = 0;
        pq.push({0, src});

        while(!pq.empty()) {
            auto [d, node] = pq.top();
            pq.pop();

            // Ignore outdated queue entry.
            if(d > dist[node]) {
                continue;
            }

            // Decode state.
            int v = node / 2;
            int p = node & 1;

            // Relax all original graph edges from v.
            for(auto [w, cost, seg]: adj[v]) {
                // Moving along segment seg toggles parity by epar[seg].
                int to = 2 * w + (p ^ epar[seg]);

                // Standard Dijkstra relaxation.
                if(d + cost < dist[to]) {
                    dist[to] = d + cost;
                    par[to] = {node, seg};
                    pq.push({dist[to], to});
                }
            }
        }
    };

    long long best = inf; // Best wall cost.
    int best_src = -1;    // Starting vertex of best odd cycle.

    vector<long long> dist;
    vector<pair<int, int>> par;

    // Try every graph vertex as the start of an odd-parity closed walk.
    for(int s = 0; s < m; s++) {
        // Start at vertex s with parity 0.
        dijkstra(2 * s, dist, par);

        // Need to return to s with parity 1.
        if(dist[2 * s + 1] < best) {
            best = dist[2 * s + 1];
            best_src = s;
        }
    }

    // Rerun Dijkstra from the best source to recover the actual path.
    dijkstra(2 * best_src, dist, par);

    vector<int> used;

    // Target is same vertex, parity 1.
    int node = 2 * best_src + 1;

    // Follow parents backward to source.
    while(par[node].first != -1) {
        // Store 1-based segment index.
        used.push_back(par[node].second + 1);

        // Move to previous state.
        node = par[node].first;
    }

    // Output minimum total cost.
    cout << best << "\n";

    // Output number of used segments.
    cout << used.size() << "\n";

    // Output segment indices.
    cout << used << "\n";
}

int main() {
    // Fast IO.
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;

    // Single test case.
    for(int test = 1; test <= T; test++) {
        read();
        solve();
    }

    return 0;
}
```

---

## 4. Python solution with detailed comments

```python
import sys
import heapq
from math import inf


def main():
    # Read all input tokens at once.
    data = sys.stdin.read().strip().split()

    # If input is empty, do nothing.
    if not data:
        return

    # Pointer into token array.
    ptr = 0

    # Number of border segments.
    n = int(data[ptr])
    ptr += 1

    # Store segment endpoints and costs.
    seg_a = []
    seg_b = []
    seg_cost = []

    for _ in range(n):
        x1 = int(data[ptr])
        y1 = int(data[ptr + 1])
        x2 = int(data[ptr + 2])
        y2 = int(data[ptr + 3])
        v = int(data[ptr + 4])
        ptr += 5

        seg_a.append((x1, y1))
        seg_b.append((x2, y2))
        seg_cost.append(v)

    # Headquarters coordinates.
    hq1 = (int(data[ptr]), int(data[ptr + 1]))
    hq2 = (int(data[ptr + 2]), int(data[ptr + 3]))

    # Map endpoint coordinate pairs to compact vertex ids.
    vertex_id = {}

    def get_id(p):
        """
        Return graph vertex id for point p.
        Create a new id if this endpoint was not seen before.
        """
        if p not in vertex_id:
            vertex_id[p] = len(vertex_id)
        return vertex_id[p]

    def crosses_up_ray(a, b, h):
        """
        Return True if segment ab crosses the upward vertical ray
        starting at point h.

        The ray is:
            x = h.x, y > h.y

        A half-open convention is used to avoid double-counting crossings
        exactly at graph vertices.
        """
        ax, ay = a
        bx, by = b
        hx, hy = h

        # Check which side of vertical line x = hx each endpoint lies on.
        sa = ax > hx
        sb = bx > hx

        # If both are on same side, segment does not cross the vertical line
        # in the required half-open sense.
        if sa == sb:
            return False

        # Compute the segment parameter t at which x = hx.
        # Because sa != sb, bx - ax is nonzero.
        t = (hx - ax) / (bx - ax)

        # y-coordinate of the intersection with x = hx.
        y_cross = ay + t * (by - ay)

        # It crosses the upward ray only if the intersection is above h.
        return y_cross > hy

    # Endpoint ids and parity label for each edge.
    eu = [0] * n
    ev = [0] * n
    epar = [0] * n

    for i in range(n):
        # Convert endpoints into graph vertices.
        eu[i] = get_id(seg_a[i])
        ev[i] = get_id(seg_b[i])

        # Crossing parity for both headquarters.
        c1 = crosses_up_ray(seg_a[i], seg_b[i], hq1)
        c2 = crosses_up_ray(seg_a[i], seg_b[i], hq2)

        # Edge label is 1 iff this edge changes the relative inside/outside
        # parity of the two headquarters.
        epar[i] = int(c1) ^ int(c2)

    # Number of graph vertices.
    m = len(vertex_id)

    # Build undirected adjacency list.
    # adj[v] contains tuples:
    #   (neighbor_vertex, edge_cost, segment_index)
    adj = [[] for _ in range(m)]

    for i in range(n):
        u = eu[i]
        v = ev[i]
        w = seg_cost[i]

        adj[u].append((v, w, i))
        adj[v].append((u, w, i))

    def dijkstra(src_state):
        """
        Dijkstra on doubled graph.

        State encoding:
            state = 2 * vertex + parity

        parity is accumulated XOR of edge labels along the walk.
        """
        total_states = 2 * m

        # Distance array.
        dist = [inf] * total_states

        # Parent array for reconstructing path.
        # parent[state] = (previous_state, segment_index_used)
        parent = [(-1, -1)] * total_states

        # Priority queue of (distance, state).
        pq = []

        # Initialize source.
        dist[src_state] = 0
        heapq.heappush(pq, (0, src_state))

        while pq:
            d, state = heapq.heappop(pq)

            # Ignore stale priority queue entries.
            if d != dist[state]:
                continue

            # Decode current vertex and parity.
            v = state // 2
            parity = state & 1

            # Traverse each original edge.
            for to_vertex, cost, seg_idx in adj[v]:
                # New parity after using this segment.
                new_parity = parity ^ epar[seg_idx]

                # Encode next state.
                next_state = 2 * to_vertex + new_parity

                # Relax edge.
                nd = d + cost
                if nd < dist[next_state]:
                    dist[next_state] = nd
                    parent[next_state] = (state, seg_idx)
                    heapq.heappush(pq, (nd, next_state))

        return dist, parent

    best_cost = inf
    best_src = -1

    # Try every vertex as the beginning/end of the closed walk.
    for s in range(m):
        # Start from vertex s with accumulated parity 0.
        dist, _ = dijkstra(2 * s)

        # We want to return to vertex s with accumulated parity 1.
        target = 2 * s + 1

        if dist[target] < best_cost:
            best_cost = dist[target]
            best_src = s

    # Re-run Dijkstra from best source to reconstruct one optimal cycle.
    dist, parent = dijkstra(2 * best_src)

    # Target state: same vertex, odd parity.
    state = 2 * best_src + 1

    used_segments = []

    # Follow parents backward until source.
    while parent[state][0] != -1:
        prev_state, seg_idx = parent[state]

        # Output uses 1-based segment indices.
        used_segments.append(seg_idx + 1)

        state = prev_state

    # Print answer.
    print(int(best_cost))
    print(len(used_segments))
    print(*used_segments)


if __name__ == "__main__":
    main()
```

---

## 5. Compressed editorial

Turn the border map into an undirected weighted planar graph: endpoints are vertices and given segments are edges.

For each edge, compute whether it crosses the upward ray from headquarters `1`, and whether it crosses the upward ray from headquarters `2`. Let:

```text
label(edge) = crosses_ray_1 XOR crosses_ray_2
```

For any cycle, the XOR of its edge labels is `1` exactly when the cycle separates the two headquarters.

Thus we need the minimum-cost cycle with odd XOR label.

Use a parity-expanded graph. State `(v, p)` means we are at vertex `v` with accumulated parity `p`. Traversing an edge with label `q` moves to parity `p XOR q`.

For every vertex `s`, run Dijkstra from `(s, 0)` and check distance to `(s, 1)`. This is the minimum odd-parity closed walk through `s`. Taking the best over all `s` gives the answer. Since all edge weights are positive, a minimum odd closed walk contains an optimal simple odd cycle.

Reconstruct the path using parent pointers and output the corresponding segment indices.