Problem:
Problem I: Wind Passages Wind Corridor is a covered passageway where strong wind is always blowing. It is a long corridor of
width W, and there are several pillars in it. Each pillar is a right prism and its face is a polygon (not
necessarily convex). In this problem, we consider two-dimensional space where the positive x -axis points the east and the
positive y -axis points the north. The passageway spans from the south to the north, and its length is
infinity. Specifically, it covers the area 0 ≤ x ≤ W . The outside of the passageway is filled with walls.
Each pillar is expressed as a polygon, and all the pillars are located within the corridor without conflicting
or touching each other. Wind blows from the south side of the corridor to the north. For each second, w unit volume of air can
be flowed at most if the minimum width of the path of the wind is w . Note that the path may fork and
merge, but never overlaps with pillars and walls. Your task in this problem is to write a program that calculates the maximum amount of air that can be
flowed through the corridor per second. Input The input consists of multiple datasets. Each dataset has the following format: The first line of the input contains two integers W and N . W is the width of the corridor, and N is the
number of pillars. W and N satisfy the following condition: 1 ≤ W ≤ 10 4 and 0 ≤ N ≤ 200. Then, N specifications of each pillar follow. Each specification starts with a line that contains a single
integer M , which is the number of the vertices of a polygon (3 ≤ M ≤ 40). The following M lines describe the shape of the polygon. The i -th line (1 ≤ i ≤ M ) contains two integers x i and y i that denote the coordinate of the i -th vertex (0 < x i < W , 0 < y i < 10 4 ). The last dataset is followed by a line containing two zeros. This line is not a part of any dataset and should not be processed. Output For each dataset, your program should print a line that contains the maximum amount of air flow per second, in unit
volume. The output may contain arbitrary number of digits after the decimal point, but the absolute error
must not exceed 10 -6 . Sample Input 5 2
4
1 1
1 2
2 2
2 1
4
3 3
3 4
4 4
4 3
0 0 Output for the Sample Input 3.41421356

Solution (Python):
from heapq import heappush, heappop
import sys
readline = sys.stdin.readline
write = sys.stdout.write
def cross2(p, q):
    return p[0]*q[1] - p[1]*q[0]
def dot2(p, q):
    return p[0]*q[0] + p[1]*q[1]
def dist2(p):
    return p[0]**2 + p[1]**2
def segment_line_dist(x, p0, p1):
    z0 = (p1[0] - p0[0], p1[1] - p0[1])
    z1 = (x[0] - p0[0], x[1] - p0[1])
    if 0 <= dot2(z0, z1) <= dist2(z0):
        return cross2(z0, z1)**2 / dist2(z0)
    z2 = (x[0] - p1[0], x[1] - p1[1])
    return min(dist2(z1), dist2(z2))

def solve():
    W, N = map(int, readline().split())
    if W == N == 0:
        return False
    PS = []
    for i in range(N):
        M = int(readline())
        P = [list(map(int, readline().split())) for i in range(M)]
        PS.append(P)

    G = [[] for i in range(N+2)]
    for i in range(N):
        Pi = PS[i]
        ni = len(Pi)
        for j in range(i+1, N):
            Pj = PS[j]
            r = 10**18
            nj = len(Pj)
            for p1 in Pi:
                for k in range(nj):
                    q1 = Pj[k-1]; q2 = Pj[k]
                    r = min(r, segment_line_dist(p1, q1, q2))
            for q1 in Pj:
                for k in range(ni):
                    p1 = Pi[k-1]; p2 = Pi[k]
                    r = min(r, segment_line_dist(q1, p1, p2))
            d = r**.5
            G[i].append((j, d))
            G[j].append((i, d))
        d = min(x for x, y in Pi)
        G[i].append((N, d))
        G[N].append((i, d))

        d = W - max(x for x, y in Pi)
        G[i].append((N+1, d))
        G[N+1].append((i, d))

    G[N].append((N+1, W))
    G[N+1].append((N, W))
    que = [(0, N)]
    dist = [10**18]*(N+2)
    dist[N] = 0
    while que:
        cost, v = heappop(que)
        if dist[v] < cost:
            continue
        for w, d in G[v]:
            if cost + d < dist[w]:
                dist[w] = cost + d
                heappush(que, (cost + d, w))
    write("%.16f\n" % dist[N+1])
    return True
while solve():
    ...

Solution (Python):
def solve():
    from itertools import combinations
    from heapq import heappush, heappop
    
    def dot(c1, c2):
        return c1.real * c2.real + c1.imag * c2.imag
    
    def cross(c1, c2):
        return c1.real * c2.imag - c1.imag * c2.real
    
    
    def d_sp(sp1, sp2, p):
        a = sp2 - sp1
        b = p - sp1
        if dot(a, b) < 0:
            return abs(b)
        c = sp1 - sp2
        d = p - sp2
        if dot(c, d) < 0:
            return abs(d)
        return abs(cross(a, b) / a)
    
    
    def d_s(p1, p2, p3, p4):
        return min(d_sp(p1, p2, p3), d_sp(p1, p2, p4), d_sp(p3, p4, p1), \
                   d_sp(p3, p4, p2))

    from sys import stdin
    
    file_input = stdin
    
    while True:
        W, N = map(int, file_input.readline().split())
        
        if W == 0:
            break
        if N == 0:
            print(W)
            continue
        
        polygons = []
        adj = [[] for i in range(N + 1)]
        adj_s = adj[0]
        goal = N + 1
        
        for i in range(1, N + 1):
            M = int(file_input.readline())
            p = [i]
            s_d = W
            g_d = W
            for j in range(M):
                x, y = map(int, file_input.readline().split())
                p.append(x + y * 1j)
                s_d = min(s_d, x)
                g_d = min(g_d, W - x)
            adj_s.append((i, s_d))
            adj[i].append((goal, g_d))
            p.append(p[1])
            polygons.append(p)
        
        for p1, p2 in combinations(polygons, 2):
            i = p1[0]
            j = p2[0]
            d = [d_s(v1, v2, v3, v4) for v3, v4 in zip(p2[1:], p2[2:]) \
                 for v1, v2 in zip(p1[1:], p1[2:])]
            
            d = min(d)
            adj[i].append((j, d))
            adj[j].append((i, d))
        
        
        PQ = [(0, 0)]
        isVisited = [False] * (N + 2)
        distance = [W] * (N + 2)
        
        distance[0] = 0
        
        while PQ:
            u_cost, u = heappop(PQ)
            
            if u == goal:
                print(u_cost)
                break
            
            if u_cost > distance[u]:
                continue
            
            isVisited[u] = True
            
            for v, v_cost in adj[u]:
                if isVisited[v]:
                    continue
                
                t_cost = distance[u] + v_cost
                if t_cost < distance[v]:
                    distance[v] = t_cost
                    heappush(PQ, (t_cost, v))

solve()