Problem:
Problem C:
Save the Energy
You were caught in a magical trap and transferred to a strange field due to its cause. This field is three-
dimensional and has many straight paths of infinite length. With your special ability, you found where
you can exit the field, but moving there is not so easy. You can move along the paths easily without your
energy, but you need to spend your energy when moving outside the paths. One unit of energy is required
per distance unit. As you want to save your energy, you have decided to find the best route to the exit
with the assistance of your computer.
Your task is to write a program that computes the minimum amount of energy required to move between
the given source and destination. The width of each path is small enough to be negligible, and so is your
size.
Input
The input consists of multiple data sets. Each data set has the following format:
N
x
s
y
s
z
s
x
t
y
t
z
t
x
1,1
y
1,1
z
1,1
x
1,2
y
1,2
z
1,2
.
    .
    .
x
N
,1
y
N
,1
z
N
,1
x
N
,2
y
N
,2
z
N
,2
N
is an integer that indicates the number of the straight paths (2 ≤
N
≤ 100). (
x
s
,
y
s
,
z
s
) and (
x
t
,
y
t
,
z
t
)
denote the coordinates of the source and the destination respectively. (
x
i
,1
,
y
i
,1
,
z
i
,1
) and (
x
i
,2
,
y
i
,2
,
z
i
,2
)
denote the coordinates of the two points that the
i
-th straight path passes. All coordinates do not exceed 30,000 in their absolute values.
The distance units between two points (
x
u
,
y
u
,
z
u
) and (
x
v
,
y
v
,
z
v
) is given by the Euclidean distance as follows:
It is guaranteed that the source and the destination both lie on paths. Also, each data set contains no
straight paths that are almost but not actually parallel, although may contain some straight paths that are
strictly parallel.
The end of input is indicated by a line with a single zero. This is not part of any data set.
Output
For each data set, print the required energy on a line. Each value may be printed with an arbitrary number
of decimal digits, but should not contain the error greater than 0.001.
Sample Input
2
0 0 0 0 2 0
0 0 1 0 0 -1
2 0 0 0 2 0
3
0 5 0 3 1 4
0 1 0 0 -1 0
1 0 1 -1 0 1
3 1 -1 3 1 1
2
0 0 0 3 0 0
0 0 0 0 1 0
3 0 0 3 1 0
0
Output for the Sample Input
1.414
2.000
3.000

Submitted solutions:

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

// 3D幾何ライブラリ
////////////////////////////////////////////////////////////////////////////////
typedef double Real;
constexpr Real eps = 1e-8; // 1000 : 10^-8, 10000 : 10^-7
inline constexpr int sgn(Real a, Real b = 0) { return (a-b < -eps) ? -1 : (a-b > eps) ? 1 : 0; }
inline constexpr Real _sqrt(Real a) { return sqrt(max(a, (Real)0)); }
struct Point3D {
    Real x, y, z;
    constexpr Point3D(Real x = 0, Real y = 0, Real z = 0) : x(x), y(y), z(z) {}
    constexpr Point3D operator+() const noexcept { return *this; }
    constexpr Point3D operator-() const noexcept { return Point3D(-x, -y, -z); }
    constexpr Point3D operator+(const Point3D &p) const { return Point3D(x + p.x, y + p.y, z + p.z); }
    constexpr Point3D operator-(const Point3D &p) const { return Point3D(x - p.x, y - p.y, z - p.z); }
    constexpr Point3D operator*(const Real &k) { return Point3D(x * k, y * k, z * k); }
    constexpr Point3D operator/(const Real &k) { return Point3D(x / k, y / k, z / k); }
    constexpr Point3D &operator+=(const Point3D &p) { return x += p.x, y += p.y, z += p.z, *this; }
    constexpr Point3D &operator-=(const Point3D &p) { return x -= p.x, y -= p.y, z -= p.z, *this; }
    constexpr Point3D &operator*=(const Real &k) { return x *= k, y *= k, z *= k, *this; }
    constexpr Point3D &operator/=(const Real &k) { return x /= k, y /= k, z /= k, *this; }
    constexpr bool operator<(const Point3D &p) const noexcept {
        if (sgn(x, p.x)) return x < p.x;
        else if (sgn(y, p.y)) return y < p.y;
        else return z < p.z;
    }
    constexpr bool operator==(const Point3D &p) const noexcept { return sgn(x, p.x) == 0 and sgn(y, p.y) == 0 and sgn(z, p.z) == 0; }
    friend istream &operator>>(istream &is, Point3D &p) { is >> p.x >> p.y >> p.z; return (is); }
    constexpr Real dot(const Point3D &p) const { return x * p.x + y * p.y + z * p.z; }
    constexpr Point3D cross(const Point3D &p) const {
        return Point3D(y*p.z - p.y*z, z*p.x - p.z*x, x*p.y - p.x*y);
    }
    constexpr Real norm() const { return _sqrt(x*x + y*y + z*z); }
    constexpr Real norm2() const { return x*x + y*y + z*z; }
    constexpr Point3D vct() const { return (*this); }
    constexpr Point3D unit() const { // 単位ベクトル
        Point3D p = (*this);
        return p / this->norm();
    }
};

Point3D vct(Point3D a, Point3D b) { return (b - a); }
Real dist(Point3D a, Point3D b) { return vct(a, b).norm(); }
Real dot(Point3D a, Point3D b) { return a.dot(b); }
Point3D cross(Point3D a, Point3D b) { return a.cross(b); }

// 線分
struct Segment3D : array<Point3D, 2> {
    Segment3D() {}
    Segment3D(Point3D a, Point3D b) { at(0) = a, at(1) = b; }
    Point3D vct() { return (at(1) - at(0)); }
    Real length() { return vct().norm(); }
    friend istream &operator>> (istream &is, Segment3D &s) {
        is >> s[0] >> s[1]; return (is);
    }
};
// 直線
struct Line3D : Segment3D {
    Line3D() {}
    Line3D(Point3D a, Point3D b) : Segment3D(a, b) {}
    Line3D(Segment3D s) : Line3D(s[0], s[1]) {}
};

// 点と直線の距離
Real point_line_distance(Point3D p, Line3D l) { return cross(l.vct().unit(), (p - l[0])).norm(); }
// 直線と直線の距離
Real line_line_distance(Line3D A, Line3D B) {
    Point3D a = A.vct(), b = B.vct();
    if (sgn(cross(a, b).norm()) == 0) { // 並行の場合
        return point_line_distance(A[0], B);
    } else {
        Point3D n = cross(a, b).unit();
        return abs(dot(vct(A[0], B[0]), n));
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    while (cin >> n, n) {
        Point3D s,g; cin >> s >> g;
        vector<Line3D> l(n);
        for (int i = 0; i < n; ++i) {
            cin >> l[i];
        }
        vector<vector<Real>> dist(n+2, vector<Real>(n+2, 1e9));
        for (int i = 0; i < n + 2; ++i) {
            dist[i][i] = 0;
        }
        for (int i = 0; i < n; ++i) {
            dist[n][i] = dist[i][n] = point_line_distance(s, l[i]);
            dist[n + 1][i] = dist[i][n + 1] = point_line_distance(g, l[i]);
        }
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                dist[i][j] = dist[j][i] = line_line_distance(l[i], l[j]);
            }
        }
        for (int k = 0; k < n + 2; ++k) {
            for (int i = 0; i < n + 2; ++i) {
                for (int j = 0; j < n + 2; ++j) {
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        printf("%.9f\n", dist[n][n + 1]);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3772
final_rank: 17

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

// 3D幾何ライブラリ
////////////////////////////////////////////////////////////////////////////////
typedef double Real;
constexpr Real eps = 1e-8; // 1000 : 10^-8, 10000 : 10^-7
inline constexpr int sgn(Real a, Real b = 0) { return (a-b < -eps) ? -1 : (a-b > eps) ? 1 : 0; }
inline constexpr Real _sqrt(Real a) { return sqrt(max(a, (Real)0)); }
struct Point3D {
    Real x, y, z;
    constexpr Point3D(Real x = 0, Real y = 0, Real z = 0) : x(x), y(y), z(z) {}
    constexpr Point3D operator+() const noexcept { return *this; }
    constexpr Point3D operator-() const noexcept { return Point3D(-x, -y, -z); }
    constexpr Point3D operator+(const Point3D &p) const { return Point3D(x + p.x, y + p.y, z + p.z); }
    constexpr Point3D operator-(const Point3D &p) const { return Point3D(x - p.x, y - p.y, z - p.z); }
    constexpr Point3D operator*(const Real &k) { return Point3D(x * k, y * k, z * k); }
    constexpr Point3D operator/(const Real &k) { return Point3D(x / k, y / k, z / k); }
    constexpr Point3D &operator+=(const Point3D &p) { return x += p.x, y += p.y, z += p.z, *this; }
    constexpr Point3D &operator-=(const Point3D &p) { return x -= p.x, y -= p.y, z -= p.z, *this; }
    constexpr Point3D &operator*=(const Real &k) { return x *= k, y *= k, z *= k, *this; }
    constexpr Point3D &operator/=(const Real &k) { return x /= k, y /= k, z /= k, *this; }
    constexpr bool operator<(const Point3D &p) const noexcept {
        if (sgn(x, p.x)) return x < p.x;
        else if (sgn(y, p.y)) return y < p.y;
        else return z < p.z;
    }
    constexpr bool operator==(const Point3D &p) const noexcept { return sgn(x, p.x) == 0 and sgn(y, p.y) == 0 and sgn(z, p.z) == 0; }
    friend istream &operator>>(istream &is, Point3D &p) { is >> p.x >> p.y >> p.z; return (is); }
    constexpr Real dot(const Point3D &p) const { return x * p.x + y * p.y + z * p.z; }
    constexpr Point3D cross(const Point3D &p) const {
        return Point3D(y*p.z - p.y*z, z*p.x - p.z*x, x*p.y - p.x*y);
    }
    constexpr Real norm() const { return _sqrt(x*x + y*y + z*z); }
    constexpr Real norm2() const { return x*x + y*y + z*z; }
    constexpr Point3D vct() const { return (*this); }
    constexpr Point3D unit() const { // 単位ベクトル
        Point3D p = (*this);
        return p / this->norm();
    }
};

Point3D vct(Point3D a, Point3D b) { return (b - a); }
Real dist(Point3D a, Point3D b) { return vct(a, b).norm(); }
Real dot(Point3D a, Point3D b) { return a.dot(b); }
Point3D cross(Point3D a, Point3D b) { return a.cross(b); }

// 線分
struct Segment3D : array<Point3D, 2> {
    Segment3D() {}
    Segment3D(Point3D a, Point3D b) { at(0) = a, at(1) = b; }
    Point3D vct() { return (at(1) - at(0)); }
    Real length() { return vct().norm(); }
    friend istream &operator>> (istream &is, Segment3D &s) {
        is >> s[0] >> s[1]; return (is);
    }
};
// 直線
struct Line3D : Segment3D {
    Line3D() {}
    Line3D(Point3D a, Point3D b) : Segment3D(a, b) {}
    Line3D(Segment3D s) : Line3D(s[0], s[1]) {}
};

// 点と直線の距離
Real point_line_distance(Point3D p, Line3D l) { return cross(l.vct().unit(), (p - l[0])).norm(); }
// 2直線の距離
Real line_line_distance(Line3D A, Line3D B) {
    Point3D a = A.vct(), b = B.vct();
    // 並行の場合
    if (sgn(cross(a, b).norm()) == 0) {
        return point_line_distance(A[0], B);
    } else {
        Point3D n = cross(a, b).unit();
        return abs(dot(vct(A[0], B[0]), n));
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    while (cin >> n, n) {
        Point3D s,g; cin >> s >> g;
        vector<Line3D> l(n);
        for (int i = 0; i < n; ++i) {
            cin >> l[i];
        }
        vector<vector<Real>> dist(n+2, vector<Real>(n+2, 1e9));
        for (int i = 0; i < n + 2; ++i) {
            dist[i][i] = 0;
        }
        for (int i = 0; i < n; ++i) {
            dist[n][i] = dist[i][n] = point_line_distance(s, l[i]);
            dist[n + 1][i] = dist[i][n + 1] = point_line_distance(g, l[i]);
        }
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                dist[i][j] = dist[j][i] = line_line_distance(l[i], l[j]);
            }
        }
        for (int k = 0; k < n + 2; ++k) {
            for (int i = 0; i < n + 2; ++i) {
                for (int j = 0; j < n + 2; ++j) {
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        printf("%.9f\n", dist[n][n + 1]);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3792
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double LD;
const int N = 105;
const LD eps = 1e-10;

inline int sgn(LD x) {
    return x > eps? 1 : x < -eps? -1 : 0;
}

struct Point {
    LD x, y, z;
    Point(LD _x = 0, LD _y = 0, LD _z = 0): x(_x), y(_y), z(_z) {}
    void input() {
        scanf("%Lf %Lf %Lf", &x, &y, &z);
    }
    bool operator == (const Point &rhs) const {
        return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0 && sgn(z - rhs.z) == 0;
    }
    Point operator + (const Point &rhs) const {
        return Point(x + rhs.x, y + rhs.y, z + rhs.z);
    }
    Point operator - (const Point &rhs) const {
        return Point(x - rhs.x, y - rhs.y, z - rhs.z);
    }
    Point operator * (const LD &rhs) const {
        return Point(x * rhs, y * rhs, z * rhs);
    }
    Point operator / (const LD &rhs) const {
        return Point(x / rhs, y / rhs, z / rhs);
    }
    LD operator * (const Point &rhs) const {
        return x * rhs.x + y * rhs.y + z * rhs.z;
    }
    Point operator ^ (const Point &rhs) const {
        return Point(y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x);
    }
    LD len2() {
        return x * x + y * y + z * z;
    }
    LD len() {
        return sqrt(len2());
    }
    Point unit() {
        return (*this) / len();
    }
};

LD PointLineDist(Point p, Point u, Point v) {
    return ((v - u) ^ (p - u)).len() / (v - u).len();
}

LD LineDist(Point u1, Point v1, Point u2, Point v2) {
    Point dir1 = v1 - u1, dir2 = v2 - u2;
    if (sgn((dir1 ^ dir2).len2()) == 0) {
        return PointLineDist(u2, u1, v1);
    }
    Point norm = ((v1 - u1) ^ (v2 - u2));
    return fabsl((u2 - u1) * norm) / norm.len();
}

int n;
Point s, t, p[N], q[N];
LD dis[N][N];

int main() {
    while (1) {
        scanf("%d", &n);
        if (!n) break;
        s.input();
        t.input();
        for (int i = 1; i<= n; ++i) {
            p[i].input();
            q[i].input();
        }
        dis[n + 1][n + 2] = dis[n + 2][n + 1] = (s - t).len();
        for (int i = 1; i <= n; ++i) {
            for (int j = i + 1; j <= n; ++j) {
                dis[i][j] = dis[j][i] = LineDist(p[i], q[i], p[j], q[j]);
            }
            dis[i][n + 1] = dis[n + 1][i] = PointLineDist(s, p[i], q[i]);
            dis[i][n + 2] = dis[n + 2][i] = PointLineDist(t, p[i], q[i]);
        }
        for (int k = 1; k <= n + 2; ++k) {
            for (int i = 1; i <= n + 2; ++i) {
                for (int j = 1; j <= n + 2; ++j) {
                    dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
                }
            }
        }
        printf("%.10Lf\n", dis[n + 1][n + 2]);
    }
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3676
final_rank: 20

code_snippet: #pragma once

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

#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b))<EPS)

class Point3d{
public:
  double x,y,z;
  
  Point3d(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
 
  Point3d operator + (const Point3d& a){
    return Point3d(x+a.x,y+a.y,z+a.z);
  }
  Point3d operator - (const Point3d& a){
    return Point3d(x-a.x,y-a.y,z-a.z);
  }
  Point3d operator * (const double& d){
    return Point3d(x*d,y*d,z*d);
  }
  Point3d operator / (const double& d){
    return Point3d(x/d,y/d,z/d);
  }
 
  bool operator < (const Point3d& p)const { return !equals(x,p.x)?x<p.x:((!equals(y,p.y))?y<p.y:(!equals(z,p.z)&&z<p.z)); }
 
  bool operator == (const Point3d& p)const{
    return equals(x,p.x) && equals(y,p.y) && equals(z,p.z);
  }
 
};
 
struct Segment3d{
  Point3d p[2];
  Segment3d(Point3d p1=Point3d(),Point3d p2=Point3d()){
    p[0] = p1, p[1] = p2;
  }
 bool operator == (const Segment3d& seg)const{
    return ( p[0] == seg.p[0] && p[1] == seg.p[1] ) || ( p[0] == seg.p[1] && p[1] == seg.p[0] );
 }
};
 
typedef Point3d Vector3d;
typedef Segment3d Line3d;
  
ostream& operator << (ostream& os,const Point3d& p){
  return os << "(" << p.x << "," << p.y << "," << p.z << ")";
}
 
ostream& operator << (ostream& os,const Segment3d& seg){
  return os << "(" << seg.p[0] << "," << seg.p[1] << ")";
}
 
double dot(const Point3d& a,const Point3d& b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}
 
Vector3d cross(const Point3d& a,const Point3d& b){
  return Vector3d(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
 
inline double norm(const Point3d &p){
  return p.x*p.x + p.y*p.y + p.z*p.z;
}
 
inline double abs(const Point3d &p){
  return sqrt(norm(p));
}
 
inline double toRad(double theta){
  return theta * M_PI / 180.0;
}

double distanceLP(Line3d line,Point3d p){
  return abs(cross(line.p[1]-line.p[0],p-line.p[0])) / abs(line.p[1]-line.p[0]);
}
 
Point3d project(Segment3d seg,Point3d p){
  Vector3d base = seg.p[1] - seg.p[0];
  double t = dot(p-seg.p[0],base) / norm(base);
  return seg.p[0] + base * t;
}
 
Point3d reflect(Segment3d seg,Point3d p){
  return p + (project(seg,p)-p) * 2.0;
}

bool on_line3d(Line3d line,Point3d p){
  return equals(abs(cross(line.p[1]-p,line.p[0]-p)),0);
}
 
bool on_segment3d(Segment3d seg,Point3d p){
  if( !on_line3d(seg,p) ) return false;
  double dist[3] = { abs(seg.p[1]-seg.p[0]), abs(p-seg.p[0]), abs(p-seg.p[1]) };  
  return on_line3d(seg,p) && equals(dist[0],dist[1]+dist[2]);
}

double distanceSP(Segment3d seg,Point3d p){
  Point3d r = project(seg,p);
  if( on_segment3d(seg,r) ) return abs(p-r);
  return min(abs(seg.p[0]-p),abs(seg.p[1]-p));
}

#pragma once

class Plane3d{
public:
  Point3d normal_vector; //法線ベクトル
  double d; // 平面方程式 normal_vector.x * x + normal_vector.y * y + normal_vector.z * z + d = 0
 
  Plane3d(Point3d normal_vector=Point3d(),double d=0):normal_vector(normal_vector),d(d){}
  Plane3d(Vector3d a,Vector3d b,Vector3d c){
    Vector3d v1 = b - a;
    Vector3d v2 = c - a;
    Vector3d tmp = cross(v1,v2);
    normal_vector = tmp / abs(tmp);
    set_d(a);
  }
 
  //法線ベクトルnormal_vectorと平面上の１点からdを計算する
  void set_d(Point3d p){
    d = dot(normal_vector,p);
  }
 
  //平面と点pの距離を求める
  double distanceP(Point3d p){
    Point3d a = normal_vector * d;//平面上の適当な点をつくる
    return abs( dot(p-a,normal_vector) );
  }
 
  //平面上でもっとも点pと近い点を求める
  Point3d nearest_point(Point3d p){
    Point3d a = normal_vector * d;
    return p - ( normal_vector * dot(p-a,normal_vector) );
  }
 
  //平面と線分が交差するか
  bool intersectS(Segment3d seg){
    Point3d a = normal_vector * d;
    double res1 = dot(a-seg.p[0],normal_vector);
    double res2 = dot(a-seg.p[1],normal_vector);
    if( res1 > res2 ) swap(res1,res2);
    //cout << res1 << " < " << res2 << endl;
    if( ( equals(res1,0.0) || res1 < 0 ) && ( equals(res2,0.0) || res2 > 0 ) ) return true;
    return false;
  }
 
  //平面と線分の交点を求める
  Point3d crosspointS(Segment3d seg){
    Point3d a = normal_vector * d;
    double dot_p0a = fabs(dot( seg.p[0]-a,normal_vector ));
    double dot_p1a = fabs(dot( seg.p[1]-a,normal_vector ));
    if( equals(dot_p0a+dot_p1a,0) ) return seg.p[0];
    return seg.p[0] + ( seg.p[1] - seg.p[0] ) * ( dot_p0a / ( dot_p0a + dot_p1a ) );
  }
 
};

#pragma once

bool point_on_the_triangle3d(Point3d tri1,Point3d tri2,Point3d tri3,Point3d p){
 
  //線分上にpがあった場合、三角形内とみなす場合は以下のコメントアウトを外す
  /*
    if( on_segment3d(Segment3d(tri1,tri2),p) ) return true;
    if( on_segment3d(Segment3d(tri2,tri3),p) ) return true;
    if( on_segment3d(Segment3d(tri3,tri1),p) ) return true;
  */
  
  vector<Point3d> vec(3);
  vec[0] = tri1, vec[1] = tri2, vec[2] = tri3;
  double area = 0;
  {
    double a = abs(vec[0]-vec[1]), b = abs(vec[1]-vec[2]), c = abs(vec[2]-vec[0]);
    double s = ( a + b + c ) / 2;
    area = sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  }
  double sum = 0;
  for(int i=0;i<3;++i) {
    double a = abs(vec[i]-vec[(i+1)%3]), b = abs(vec[(i+1)%3]-p), c = abs(p-vec[i]);
    double s = ( a + b + c ) / 2;
    sum += sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  }
  return equals(sum,area);
}

#pragma once

// 直線 l1 と l2 は平行か？
bool isParallel(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
  return equals(tmp,0.0);
}

// 直線 l1 と l2 を結ぶような線分であって最も距離が短いものを返す
// Note: l1 と l2 が平行な時には使用できないので注意
Segment3d nearest_segmentLL(Line3d l1,Line3d l2){
  assert(!isParallel(l1,l2)); // 平行な場合は使用不可
  // l1.p[0] = A, l1.p[1] = B, l2.p[0] = C, l2.p[1] = D
  Vector3d AB = l1.p[1] - l1.p[0];
  Vector3d CD = l2.p[1] - l2.p[0];
  Vector3d AC = l2.p[0] - l1.p[0];
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double d1 = (dot(n1,AC)-dot(n1,n2)*dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  double d2 = (dot(n1,n2)*dot(n1,AC)-dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  return Segment3d(l1.p[0]+n1*d1,l2.p[0]+n2*d2);
}
 
// 直線 l1 と l2 は交差するか？
bool intersectLL(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
 
  //そもそもl1,l2が直線じゃない
  if( equals(abs(B-A),0.0) || equals(abs(D-C),0.0) ){
    // この場合は注意
    // そもそも与えられた線分が線分になっていないので、交差するかどうかは判定できない
    return false;
  }
 
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
 
  if( equals(tmp,0.0) ) return 0; // 直線が平行
 
  Segment3d ns = nearest_segmentLL(l1,l2);
  if( ns.p[0] == ns.p[1] ) return true;
  return false;
}

// 線分 seg1 と seg2 は交差しているか？
bool intersectSS(Segment3d seg1,Segment3d seg2){
  if( isParallel(seg1,seg2) ) return false;
  Segment3d seg = nearest_segmentLL(seg1,seg2);
  if( !( seg.p[0] == seg.p[1] ) ) return false;
  Point3d cp = seg.p[1];
  return on_segment3d(seg1,cp) && on_segment3d(seg2,cp);
}

Line3d line[110];
Point3d source_p,sink_p;
int source,sink;
double fw[110][110];

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)

const int IINF = INT_MAX;

int main(){
  int N;
  while(cin>>N,N){
    cin >> source_p.x >> source_p.y >> source_p.z >> sink_p.x >> sink_p.y >> sink_p.z;
 
    source = sink = -1;
    rep(i,N){
      rep(j,2)cin >> line[i].p[j].x >> line[i].p[j].y >> line[i].p[j].z;
      if( on_line3d(line[i],source_p) ) {
	assert( source == -1 );
	source = i;
      }
      if( on_line3d(line[i],sink_p) ) {
	assert( sink == -1 );
	sink = i;
      }
    }
    assert( source != -1 && sink != -1 );
 
    rep(i,N)rep(j,N)fw[i][j] = IINF;
    rep(i,N)REP(j,i,N){
      if( i == j ) fw[i][j] = 0;
      else if( isParallel(line[i],line[j]) ){
	double area = abs( cross(line[i].p[1]-line[i].p[0],line[j].p[1]-line[i].p[0]) ) ;
	fw[i][j] = fw[j][i] = area / abs(line[i].p[1]-line[i].p[0]);
      }
      else if(!intersectLL(line[i],line[j])){
	Segment3d seg = nearest_segmentLL(line[i],line[j]);
	fw[i][j] = fw[j][i] = abs(seg.p[1]-seg.p[0]);
      } 
    }
 
    rep(k,N)rep(i,N)rep(j,N)if(!equals(fw[i][k],IINF) && !equals(fw[k][j],IINF))fw[i][j] = min(fw[i][j],fw[i][k]+fw[k][j]);
    printf("%.5f\n",fw[source][sink]);
  }
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3304
final_rank: 19

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

const double INF = 1e9;

struct Point{
    double x,y,z;
};

using Vector = Point;
using Line = pair<Point,Point>;

double sq(double z){
    return z*z;
}

double size(Vector v){
    return sqrt(sq(v.x) + sq(v.y) + sq(v.z));
}

double Dot(Point a, Point b){
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

Vector Cross(Point a, Point b){
    return Vector({a.y*b.z-b.y*a.z, a.z*b.x-b.z*a.x, a.x*b.y-b.x*a.y});
}

double dist(Point a, Point b){
    Vector v({a.x-b.x, a.y-b.y, a.z-b.z});
    return size(v);
}

double distLP(Line l, Point p){
    Vector u({l.fi.x-l.se.x, l.fi.y-l.se.y, l.fi.z-l.se.z});
    double usz = size(u);
    u.x /= usz;
    u.y /= usz;
    u.z /= usz;

    Vector a({p.x-l.fi.x, p.y-l.fi.y, p.z-l.fi.z});
    double sw = Dot(a,u);
    Vector w({sw*u.x, sw*u.y, sw*u.z});

    Point h({l.fi.x+w.x, l.fi.y+w.y, l.fi.z+w.z});
    return dist(p,h);
}

double distLL(Line l, Line m){
    Vector vl({l.fi.x-l.se.x, l.fi.y-l.se.y, l.fi.z-l.se.z});
    Vector vm({m.fi.x-m.se.x, m.fi.y-m.se.y, m.fi.z-m.se.z});

    Vector s({l.fi.x-m.fi.x, l.fi.y-m.fi.y, l.fi.z-m.fi.z});
    Vector t = Cross(vl,vm);
    return abs(Dot(s,t))/size(t);
}

Point READ(){
    double x,y,z;
    cin >>x >>y >>z;
    return {x,y,z};
}

int main(){
    int n;
    while(cin >>n,n){
        Point s = READ(), g = READ();
        vector<Line> l(n);
        rep(i,n){
            l[i].fi = READ();
            l[i].se = READ();
        }

        vector<vector<double>> d(n+2, vector<double>(n+2,INF));

        d[n][n+1] = d[n+1][n] = dist(s,g);
        rep(i,n){
            d[i][n] = d[n][i] = distLP(l[i],s);
            d[i][n+1] = d[n+1][i] = distLP(l[i],g);
        }
        rep(i,n)rep(j,i) d[i][j] = d[j][i] = distLL(l[i], l[j]);

        // rep(i,n+2){
        //     rep(j,n+2) printf(" %.4f", d[i][j]);
        //     printf("\n");
        // }

        rep(k,n+2)rep(i,n+2)rep(j,n+2) d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
        printf("%.10f\n", d[n][n+1]);
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3280
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e12;
 
struct Point{
    double x,y,z;
    Point(double x, double y, double z):x(x), y(y), z(z){}
    Point(){}
    Point &operator +=(const Point &a){ x+=a.x; y+=a.y; z+=a.z; return *this; }
    Point &operator -=(const Point &a){ x-=a.x; y-=a.y; z-=a.z; return *this; }
    Point &operator *=(const double &a){ x*=a; y*=a; z*=a; return *this; }
    Point operator +(const Point &a) const{ return Point(x+a.x, y+a.y, z+a.z); }
    Point operator -(const Point &a) const{ return Point(x-a.x, y-a.y, z-a.z); }
    Point operator *(const double &a) const{ return Point(a*x, a*y, a*z); }
    Point operator -() { return Point(-x, -y, -z); }
};
struct Obj{
    Point p;
    double r;
    Obj(Point &p, double r):p(p), r(r){}
    Obj(){}
};
 
double dot(const Point &a, const Point &b){
    return a.x*b.x +a.y*b.y +a.z*b.z;
}
Point cross(const Point &a, const Point &b){
    return Point(a.y*b.z -a.z*b.y, a.z*b.x -a.x*b.z, a.x*b.y -a.y*b.x);
}
double abs(const Point &a){
    return sqrt(dot(a, a));
}
Point unit(const Point &a){
    return a *(1/abs(a));
}
bool operator ==(const Point &a, const Point &b){
    return abs(a-b) < EPS;
}

Point projectionLP3(Point p, Point q, Point c){
    double t = dot(unit(q-p), c-p);
    return p +unit(q-p) *t;
}

double distanceLP3(Point p, Point q, Point c){
    return abs(projectionLP3(p, q, c) -c);
}

bool intersectLP3(Point p, Point q, Point c){
    return abs(cross(p-c, q-c)) < EPS;
}

bool isParallel(Point a, Point b, Point c, Point d){
    return abs(cross(b-a, d-c)) < EPS;
}

double distanceLL3(Point a, Point b, Point c, Point d){
    if(isParallel(a, b, c, d)){
        return distanceLP3(a, b, c);
    }
    Point v[2] = {unit(b-a), unit(d-c)};
    double d0 = (dot(v[0], c-a) -dot(v[1], c-a)*dot(v[0], v[1])) /(1 -dot(v[0], v[1])*dot(v[0], v[1]));
    double d1 = (-dot(v[1], c-a) +dot(v[0], c-a)*dot(v[0], v[1])) /(1 -dot(v[0], v[1])*dot(v[0], v[1]));
    return abs((a +v[0]*d0) -(c +v[1]*d1));
}

int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        vector<vector<Point> > p(n, vector<Point>(2));
        Point s, t;
        cin >> s.x >> s.y >> s.z;
        cin >> t.x >> t.y >> t.z;
        int sidx=-1, tidx=-1;
        for(int i=0; i<n; i++){
            cin >> p[i][0].x >> p[i][0].y >> p[i][0].z;
            cin >> p[i][1].x >> p[i][1].y >> p[i][1].z;
            if(intersectLP3(p[i][0], p[i][1], s)){
                sidx = i;
            }
            if(intersectLP3(p[i][0], p[i][1], t)){
                tidx = i;
            }
        }
        if(sidx==-1) cerr << "sidx == -1" << endl;
        if(tidx==-1) cerr << "tidx == -1" << endl;

        vector<vector<double> > adj(n, vector<double>(n, INF));
        for(int i=0; i<n; i++){
            for(int j=i; j<n; j++){
                adj[i][j] = adj[j][i] = distanceLL3(p[i][0], p[i][1], p[j][0], p[j][1]);
            }
        }
        for(int k=0; k<n; k++){
            for(int i=0; i<n; i++){
                for(int j=0; j<n; j++){
                    adj[i][j] = min(adj[i][j], adj[i][k] +adj[k][j]);
                }
            }
        }
        cout << fixed << setprecision(10);
        cout << adj[sidx][tidx] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3304
final_rank: 15

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 100

enum Type{
	FROM_start,
	FROM_goal,
};


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

	Point(){
		x = y = z = 0.0;
	}

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

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

typedef Point Vector;

struct Line{

	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

struct Info{
	Info(int arg_line_id,double arg_sum_dist){
		line_id = arg_line_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Info &arg) const{
		return sum_dist > arg.sum_dist;
	}
	int line_id;
	double sum_dist;
};

int N;
Point start,goal;
Line line[NUM];
double dist[NUM][NUM],min_dist[NUM][2];

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

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

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

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

double calc_dist1(Line line,Point point){
    return abs(cross(line.p[1]-line.p[0],point-line.p[0]))/abs(line.p[1]-line.p[0]);
}

double calc_dist2(int a,int b){

	Vector u1 = line[a].p[1]-line[a].p[0];
	Vector u2 = line[b].p[1]-line[b].p[0];
	Vector u3 = line[b].p[0]-line[a].p[0];

	if(abs(cross(u1,u2)) < EPS){
		return calc_dist1(line[a],line[b].p[0]);
	}
	return abs(dot(cross(u1,u2),u3)/abs(cross(u1,u2)));
}

double calc_dist3(Point a,Point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}

void dijkstra(Type type){

	for(int i = 0; i < N; i++)min_dist[i][type] = DBL_MAX;

	priority_queue<Info> Q;

	Point base;

	if(type == FROM_start){
		base = start;
	}else{
		base = goal;
	}

	for(int i = 0; i < N; i++){
		min_dist[i][type] = calc_dist1(line[i],base);
		Q.push(Info(i,min_dist[i][type]));
	}

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().line_id][type]){
			Q.pop();
			continue;
		}

		for(int i = 0; i < N; i++){
			if(i == Q.top().line_id)continue;

			if(min_dist[i][type] > Q.top().sum_dist+dist[Q.top().line_id][i]){
				min_dist[i][type] = Q.top().sum_dist+dist[Q.top().line_id][i];
				Q.push(Info(i,min_dist[i][type]));
			}
		}
		Q.pop();
	}
}

void func(){

	scanf("%lf %lf %lf %lf %lf %lf",&start.x,&start.y,&start.z,&goal.x,&goal.y,&goal.z);

	for(int i = 0; i < N; i++){
		scanf("%lf %lf %lf %lf %lf %lf",&line[i].p[0].x,&line[i].p[0].y,&line[i].p[0].z,&line[i].p[1].x,&line[i].p[1].y,&line[i].p[1].z);
	}

	double tmp_dist;

	//2直線間の距離を計算
	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			tmp_dist = calc_dist2(i,k);
			dist[i][k] = tmp_dist;
			dist[k][i] = tmp_dist;
		}
	}

	dijkstra(FROM_start);
	dijkstra(FROM_goal);

	double ans = calc_dist3(start,goal); //直接の距離

	for(int i = 0; i < N; i++){
		ans = min(ans,min_dist[i][FROM_start]+min_dist[i][FROM_goal]);
	}

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

int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3244
final_rank: 13

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_N = 100;

const double DINF = 1e70;

/* typedef */

typedef pair<double,int> pdi;
typedef vector<pdi> vpdi;

template <typename T>
struct Pt3D {
  T x, y, z;

  Pt3D() {}
  Pt3D(T _x, T _y, T _z) { x = _x; y = _y; z = _z; }

  bool operator==(const Pt3D<T>& pt) const {
    return x == pt.x && y == pt.y && z == pt.z;
  }

  bool operator<(const Pt3D<T>& pt) const {
    return x < pt.x || (x == pt.x && (y < pt.y || (y == pt.y && z < pt.z)));
  }
  
  Pt3D<T> operator+(const Pt3D<T>& pt) const {
    return Pt3D<T>(x + pt.x, y + pt.y, z + pt.z);
  }

  Pt3D<T> operator-(const Pt3D<T>& pt) const {
    return Pt3D<T>(x - pt.x, y - pt.y, z - pt.z);
  }
  
  Pt3D<T> operator-() const { return Pt3D<T>(-x, -y, -z); }
  Pt3D<T> operator*(const T& t) const { return Pt3D<T>(x * t, y * t, z * t); }
  Pt3D<T> operator/(const T& t) const { return Pt3D<T>(x / t, y / t, z / t); }

  T dot(const Pt3D<T>& v) const { return x * v.x + y * v.y + z * v.z; }

  Pt3D<T> cross(const Pt3D<T>& v) const {
    return Pt3D<T>(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
  }

  T d2() const { return x * x + y * y + z * z; }
  double d() const { return sqrt(d2()); }
  Pt3D<T> normalize() const { return *this / d(); }

  void print(string format) {
    printf(("(" + format + ", " + format + ", " + format + ")\n").c_str(),
           x, y, z);
  }
  void print() { print("%.6lf"); }
};

typedef Pt3D<double> pt3d;

struct Line {
  pt3d p0, p1, v;
};

/* global variables */

int n;
pt3d st, gl;
Line lines[MAX_N];
double dls[MAX_N][MAX_N], dists[MAX_N];

/* subroutines */

bool on_line(const pt3d& p0, const Line& l0) {
  return (p0 - l0.p0).cross(l0.v).d2() == 0.0;
}

double det3(const pt3d& v0, const pt3d& v1, const pt3d& v2) {
  return
    v0.x * v1.y * v2.z + v0.y * v1.z * v2.x + v0.z * v1.x * v2.y
    - v0.z * v1.y * v2.x - v0.y * v1.x * v2.z - v0.x * v1.z * v2.y;
}

double dist_lines(const Line& l0, const Line& l1) {
  pt3d v00 = l1.p0 - l0.p0;
  pt3d v01 = l1.p1 - l0.p0;

  if (det3(l0.v, v00, v01) == 0.0) {	// on plane
    if (l0.v.cross(l1.v).d2() > 0.0) return 0.0; // not parallel -> cross
    return v00.cross(v01).d() / l1.v.d(); // parallel
  }

  // not on plane
  pt3d nv = l0.v.cross(l1.v).normalize();
  return abs(v00.dot(nv));
}

/* main */

int main() {
  for (;;) {
    cin >> n;
    if (n == 0) break;

    cin >> st.x >> st.y >> st.z;
    cin >> gl.x >> gl.y >> gl.z;

    for (int i = 0; i < n; i++) {
      cin >> lines[i].p0.x >> lines[i].p0.y >> lines[i].p0.z
	  >> lines[i].p1.x >> lines[i].p1.y >> lines[i].p1.z;
      lines[i].v = lines[i].p1 - lines[i].p0;
    }

    int sti = -1, gli = -1;

    for (int i = 0; i < n; i++) {
      if (sti < 0 && on_line(st, lines[i])) sti = i;
      if (gli < 0 && on_line(gl, lines[i])) gli = i;
    }
    //printf("sti=%d, gli=%d\n", sti, gli);

    for (int i = 0; i < n; i++) {
      dists[i] = DINF;
      dls[i][i] = 0.0;
      for (int j = i + 1; j < n; j++)
	dls[i][j] = dls[j][i] = dist_lines(lines[i], lines[j]);
    }

    priority_queue<pdi,vpdi,greater<pdi> > q;
    q.push(pdi(0.0, sti));
    dists[sti] = 0.0;

    while (! q.empty()) {
      pdi u = q.top();
      q.pop();

      double ud = u.first;
      int ui = u.second;
      if (ud != dists[ui]) continue;
      if (ui == gli) break;

      for (int vi = 0; vi < n; vi++) {
	if (ui == vi) continue;

	double vd = ud + dls[ui][vi];
	if (dists[vi] > vd) {
	  dists[vi] = vd;
	  q.push(pdi(vd, vi));
	}
      }
    }

    printf("%.3lf\n", dists[gli]);
  }

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1352
final_rank: 1

code_snippet: #include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>

using namespace std;
static const double INF = 1e10;
static const double EPS = 1e-8;
inline int sign(double x){ return abs(x) < EPS ? 0 : (x > 0 ? 1 : -1); }

struct Point3D {
	double x, y, z;
	Point3D() : x(0), y(0), z(0) { }
	Point3D(double x, double y, double z) : x(x), y(y), z(z) { }

	Point3D operator-() const { return Point3D(-x, -y, -z); }
	Point3D operator+(const Point3D &p) const {
		return Point3D(x + p.x, y + p.y, z + p.z);
	}
	Point3D operator-(const Point3D &p) const {
		return Point3D(x - p.x, y - p.y, z - p.z);
	}
	Point3D operator*(const double s) const {
		return Point3D(x * s, y * s, z * s);
	}
	Point3D operator/(const double s) const {
		return Point3D(x / s, y / s, z / s);
	}
};

struct Line3D {
	Point3D a, b;
	Line3D() : a(), b() { }
	Line3D(const Point3D &a, const Point3D &b) : a(a), b(b) { }
};

struct Sphere {
	Point3D c;
	double r;
	Sphere() : c(), r(0) { }
	Sphere(const Point3D &c, double r) : c(c), r(r) { }
};

inline double dot(const Point3D &a, const Point3D &b){
	return a.x * b.x + a.y * b.y + a.z * b.z;
}
inline Point3D cross(const Point3D &a, const Point3D &b){
	return Point3D(
		a.y * b.z - a.z * b.y,
		a.z * b.x - a.x * b.z,
		a.x * b.y - a.y * b.x);
}
inline double norm(const Point3D &p){
	return p.x * p.x + p.y * p.y + p.z * p.z;
}
inline double abs(const Point3D &p){
	return sqrt(norm(p));
}
inline Point3D unit(const Point3D &p){
	return p / abs(p);
}
inline Point3D vec(const Line3D &l){
	return l.b - l.a;
}

inline Point3D projection(const Line3D &l, const Point3D &p){
	const Point3D v = vec(l);
	return l.a + v * (dot(p - l.a, v) / norm(v));
}
inline Point3D reflection(const Line3D &l, const Point3D &p){
	const Point3D q = projection(l, p);
	return q + q - p;
}

inline bool intersectLP(const Line3D &l, const Point3D &p){
	return !sign(norm(cross(p - l.a, vec(l))));
}
inline bool intersectSP(const Line3D &l, const Point3D &p){
	const Point3D a = p - l.a, b = vec(l);
	if(norm(a) < EPS || norm(a - b) < EPS){ return true; }
	if(norm(cross(a, b)) > EPS){ return false; }
	if(sign(a.x * b.x) < 0){ return false; }
	if(sign(a.y * b.y) < 0){ return false; }
	if(sign(a.z * b.z) < 0){ return false; }
	return norm(a) < norm(b);
}
inline double distanceLP(const Line3D &l, const Point3D &p){
	const Point3D q = projection(l, p);
	return abs(p - q);
}
inline double distanceSP(const Line3D &l, const Point3D &p){
	const Point3D u = p - l.a;
	const Point3D v = projection(Line3D(Point3D(), vec(l)), u);
	if(intersectSP(Line3D(Point3D(), vec(l)), v)){ return abs(u - v); }
	return sqrt(min(norm(p - l.a), norm(p - l.b)));
}
inline double distanceLL(const Line3D &s, const Line3D &t){
	const Point3D vs = unit(vec(s)), vt = unit(vec(t));
	const double f = 1.0 - pow(dot(vs, vt), 2);
	if(abs(f) < EPS){ return distanceLP(s, t.a); }
	const double a = dot(s.a - t.a, vt);
	const double b = dot(t.a - s.a, vs);
	const double c = dot(vs, vt);
	const double d = 1.0 / f;
	const double x = d * (b + c * a);
	const double y = d * (c * b + a);
	return abs((s.a + vs * x) - (t.a + vt * y));
}

vector<Point3D> crosspointCL(const Sphere &s, const Line3D &l){
	const Point3D &p = projection(l, s.c);
	const double d2 = norm(s.c - p);
	if(d2 > s.r * s.r + EPS){ return vector<Point3D>(); }
	if(d2 > s.r * s.r - EPS){ return vector<Point3D>(1, p); }
	const double sc = sqrt(s.r * s.r - d2);
	vector<Point3D> ret;
	ret.push_back(p + unit(vec(l)) * sc);
	ret.push_back(p - unit(vec(l)) * sc);
	return ret;
}
vector<Point3D> crosspointCS(const Sphere &s, const Line3D &l){
	const vector<Point3D> ps = crosspointCL(s, l);
	vector<Point3D> ret;
	for(int i = 0; i < ps.size(); ++i){
		if(intersectSP(l, ps[i])){ ret.push_back(ps[i]); }
	}
	return ret;
}

bool intersectCL(const Sphere &s, const Line3D &l){
	return distanceLP(l, s.c) < s.r + EPS;
}
bool intersectCS(const Sphere &s, const Line3D &l){
	return !crosspointCS(s, l).empty();
}

int main(){
	ios_base::sync_with_stdio(false);
	cout << setiosflags(ios::fixed) << setprecision(10);
	while(true){
		int n;
		cin >> n;
		if(n == 0){ break; }
		Point3D s, t;
		cin >> s.x >> s.y >> s.z;
		cin >> t.x >> t.y >> t.z;
		vector<Line3D> lines(n);
		for(int i = 0; i < n; ++i){
			double x1, y1, z1, x2, y2, z2;
			cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
			lines[i] = Line3D(Point3D(x1, y1, z1), Point3D(x2, y2, z2));
		}
		vector< vector<double> > mat(n, vector<double>(n, INF));
		for(int i = 0; i < n; ++i){
			mat[i][i] = 0.0;
			for(int j = 0; j < i; ++j){
				mat[i][j] = mat[j][i] = distanceLL(lines[i], lines[j]);
			}
		}
		for(int k = 0; k < n; ++k){
			for(int i = 0; i < n; ++i){
				for(int j = 0; j < n; ++j){
					mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
				}
			}
		}
		double answer = abs(t - s);
		for(int i = 0; i < n; ++i){
			const double ds = distanceLP(lines[i], s);
			for(int j = 0; j < n; ++j){
				const double dt = distanceLP(lines[j], t);
				answer = min(answer, ds + dt + mat[i][j]);
			}
		}
		cout << answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 1412
final_rank: 9

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
 
using namespace std;
 
typedef long long ll;
typedef pair <int,int> P;
typedef pair <int,P > PP;
 
int tx[] = {0,1,0,-1};
int ty[] = {-1,0,1,0};
 
static const double EPS = 1e-10;

class Point {
public:
  double _x;
  double _y;
  double _z;
  Point (double x,double y,double z) :
    _x(x), _y(y), _z(z) {}
  Point operator-(const Point& p) const {
    return Point(_x - p._x,
                 _y - p._y,
                 _z - p._z);
  }
  Point operator+(const Point& p) const {
    return Point(_x + p._x,
                 _y + p._y,
                 _z + p._z);
  }
  Point operator*(const double t) const {
    return Point(_x * t,
                 _y * t,
                 _z * t);
  }
  Point operator*(const Point&p) const {
    return Point(_x * p._x,
                 _y * p._y,
                 _z * p._z);
  }
  Point operator/(const double t) const {
    return Point(_x / t,
                 _y / t,
                 _z / t);
  }
  void print_vec() const{
    printf("(%lf,%lf,%lf)\n",_x,_y,_z);
  }
};

class Line : public vector<Point> {
public:
  Line(const Point& p1,const Point& p2) {
    push_back(p1);
    push_back(p2);
  }
};

double norm(const Point& p){
  return sqrt(p._x * p._x + p._y * p._y + p._z * p._z);
}

Point unit(const Point& p){
  return p/norm(p);
}

double dot(const Point& p1,const Point& p2){
  return p1._x * p2._x + p1._y * p2._y + p1._z * p2._z;
}

Point cross(const Point& p1,const Point& p2){
  return Point(p1._y * p2._z - p1._z * p2._y,
               p1._z * p2._x - p1._x * p2._z,
               p1._x * p2._y - p1._y * p2._x);
}

Point projection(const Line& l,const Point& p){
  double t = dot(p - l[0],l[0]-l[1]) / norm(l[0] - l[1]);
  return l[0] + unit(l[0] - l[1]) * t;
}

bool EQ(const Point& s,const Point& t) {
  if((t._x - EPS <= s._x && s._x <= t._x + EPS)
     && (t._y - EPS <= s._y && s._y <= t._y + EPS)
     && (t._z - EPS <= s._z && s._z <= t._z + EPS)) return true;
  return false;
}

bool parallelLL(const Line &l, const Line &m) {
  return EQ(cross(l[1]-l[0], m[1]-m[0]),Point(0,0,0));
}

bool intersectLP(const Line &l, const Point &p) {
  return (norm(cross(l[1]-p, l[0]-p)) < EPS);
}

double distanceLP(const Line& l,const Point& p){
  if(intersectLP(l,p)) return 0;
  return norm(p - projection(l,p));
}

double distanceLL(const Line& l,const Line& m){
  if(parallelLL(l,m)) return distanceLP(l,m[0]);

  const Point V1 = l[1] - l[0];
  const Point V2 = m[1] - m[0];
  const Point V3 = m[0] - l[0];
  return abs(dot(cross(V1,V2),V3)/norm(cross(V1,V2)));
}

double dp[105][105];

int main(){
  int num_of_straight_paths;
  while(~scanf("%d",&num_of_straight_paths)){
    if(num_of_straight_paths == 0) break;

    double sx,sy,sz;
    double gx,gy,gz;
    scanf("%lf %lf %lf",&sx,&sy,&sz);
    scanf("%lf %lf %lf",&gx,&gy,&gz);
    
    vector<Line> lines;
    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      double x[2],y[2],z[2];
      for(int i = 0; i < 2; i++){
        scanf("%lf %lf %lf",&x[i],&y[i],&z[i]);
      }
      lines.push_back(Line(Point(x[0],y[0],z[0]),
                           Point(x[1],y[1],z[1])));

    }

    memset(dp,0,sizeof(dp));

    dp[0][num_of_straight_paths+1] 
      = dp[num_of_straight_paths+1][0]
      = norm(Point(sx,sy,sz) - Point(gx,gy,gz));

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[0][path_i + 1]
        = dp[path_i + 1][0]
        = distanceLP(lines[path_i],Point(sx,sy,sz));
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[num_of_straight_paths + 1][path_i + 1]
        = dp[path_i + 1][num_of_straight_paths + 1]
        = distanceLP(lines[path_i],Point(gx,gy,gz));
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      for(int path_j = path_i + 1; path_j < num_of_straight_paths; path_j++){
        dp[path_i + 1][path_j + 1]
          = dp[path_j + 1][path_i + 1]
          = distanceLL(lines[path_i],lines[path_j]);
      }
    }

    for(int k=0;k<=num_of_straight_paths+1;k++){
      for(int i=0;i<=num_of_straight_paths+1;i++){
        for(int j=0;j<=num_of_straight_paths+1;j++){
          dp[i][j] = min(dp[i][k] + dp[k][j],dp[i][j]);
        }
      }
    }

    printf("%lf\n",dp[0][num_of_straight_paths+1]);
  }
}
accuracy: 1
time_ms: 80
memory_kb: 1356
final_rank: 7

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
 
using namespace std;
 
typedef long long ll;
typedef pair <int,int> P;
typedef pair <int,P > PP;
 
int tx[] = {0,1,0,-1};
int ty[] = {-1,0,1,0};
 
static const double EPS = 1e-10;

class Point {
public:
  double _x;
  double _y;
  double _z;
  Point (double x,double y,double z) :
    _x(x), _y(y), _z(z) {}
  Point operator-(const Point& p) const {
    return Point(_x - p._x,
                 _y - p._y,
                 _z - p._z);
  }
  Point operator+(const Point& p) const {
    return Point(_x + p._x,
                 _y + p._y,
                 _z + p._z);
  }
  Point operator*(const double t) const {
    return Point(_x * t,
                 _y * t,
                 _z * t);
  }
  Point operator*(const Point&p) const {
    return Point(_x * p._x,
                 _y * p._y,
                 _z * p._z);
  }
  Point operator/(const double t) const {
    return Point(_x / t,
                 _y / t,
                 _z / t);
  }
  void print_vec() const{
    printf("(%lf,%lf,%lf)\n",_x,_y,_z);
  }
};

class Line : public vector<Point> {
public:
  Line(const Point& p1,const Point& p2) {
    push_back(p1);
    push_back(p2);
  }
};

double norm(const Point& p){
  return sqrt(p._x * p._x + p._y * p._y + p._z * p._z);
}

Point unit(const Point& p){
  return p/norm(p);
}

double dot(const Point& p1,const Point& p2){
  return p1._x * p2._x + p1._y * p2._y + p1._z * p2._z;
}

Point cross(const Point& p1,const Point& p2){
  return Point(p1._y * p2._z - p1._z * p2._y,
               p1._z * p2._x - p1._x * p2._z,
               p1._x * p2._y - p1._y * p2._x);
}

Point projection(const Line& l,const Point& p){
  double t = dot(p - l[0],l[0]-l[1]) / norm(l[0] - l[1]);
  return l[0] + unit(l[0] - l[1]) * t;
}

bool EQ(const Point& s,const Point& t) {
  if((t._x - EPS <= s._x && s._x <= t._x + EPS)
     && (t._y - EPS <= s._y && s._y <= t._y + EPS)
     && (t._z - EPS <= s._z && s._z <= t._z + EPS)) return true;
  return false;
}

bool parallelLL(const Line &l, const Line &m) {
  return EQ(cross(l[1]-l[0], m[1]-m[0]),Point(0,0,0));
}

bool intersectLP(const Line &l, const Point &p) {
  return (norm(cross(l[1]-p, l[0]-p)) < EPS);
}

double distanceLP(const Line& l,const Point& p){
  if(intersectLP(l,p)) return 0;
  return norm(p - projection(l,p));
}

double distanceLL(const Line& l,const Line& m){
  if(parallelLL(l,m)) return distanceLP(l,m[0]);

  Point V1 = l[1] - l[0];
  Point V2 = m[1] - m[0];
  Point V3 = m[0] - l[0];
  double dist = abs(dot(cross(V1,V2),V3)/norm(cross(V1,V2)));
  return dist;
}

double dp[105][105];

int main(){
  int num_of_straight_paths;
  while(~scanf("%d",&num_of_straight_paths)){
    if(num_of_straight_paths == 0) break;

    double sx,sy,sz;
    double gx,gy,gz;
    scanf("%lf %lf %lf",&sx,&sy,&sz);
    scanf("%lf %lf %lf",&gx,&gy,&gz);
    
    vector<Line> lines;
    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      double x[2],y[2],z[2];
      for(int i = 0; i < 2; i++){
        scanf("%lf %lf %lf",&x[i],&y[i],&z[i]);
      }
      lines.push_back(Line(Point(x[0],y[0],z[0]),
                           Point(x[1],y[1],z[1])));

    }

    memset(dp,0,sizeof(dp));

    dp[0][num_of_straight_paths+1] 
      = dp[num_of_straight_paths+1][0]
      = norm(Point(sx,sy,sz) - Point(gx,gy,gz));

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[0][path_i + 1]
        = dp[path_i + 1][0]
        = distanceLP(lines[path_i],Point(sx,sy,sz));
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[num_of_straight_paths + 1][path_i + 1]
        = dp[path_i + 1][num_of_straight_paths + 1]
        = distanceLP(lines[path_i],Point(gx,gy,gz));
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      for(int path_j = path_i + 1; path_j < num_of_straight_paths; path_j++){
        dp[path_i + 1][path_j + 1]
          = dp[path_j + 1][path_i + 1]
          = distanceLL(lines[path_i],lines[path_j]);
      }
    }

    for(int k=0;k<=num_of_straight_paths+1;k++){
      for(int i=0;i<=num_of_straight_paths+1;i++){
        for(int j=0;j<=num_of_straight_paths+1;j++){
          dp[i][j] = min(dp[i][k] + dp[k][j],dp[i][j]);
        }
      }
    }

    printf("%lf\n",dp[0][num_of_straight_paths+1]);
  }
}
accuracy: 1
time_ms: 80
memory_kb: 1356
final_rank: 7

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
 
using namespace std;
 
typedef long long ll;
typedef pair <int,int> P;
typedef pair <int,P > PP;
 
int tx[] = {0,1,0,-1};
int ty[] = {-1,0,1,0};
 
static const double EPS = 1e-10;

class Point {
public:
  double _x;
  double _y;
  double _z;
  Point (double x,double y,double z) :
    _x(x), _y(y), _z(z) {}
  Point operator-(const Point& p) const {
    return Point(_x - p._x,
                 _y - p._y,
                 _z - p._z);
  }
  Point operator+(const Point& p) const {
    return Point(_x + p._x,
                 _y + p._y,
                 _z + p._z);
  }
  Point operator*(const double t) const {
    return Point(_x * t,
                 _y * t,
                 _z * t);
  }
  Point operator*(const Point&p) const {
    return Point(_x * p._x,
                 _y * p._y,
                 _z * p._z);
  }
  Point operator/(const double t) const {
    return Point(_x / t,
                 _y / t,
                 _z / t);
  }
  void print_vec() const{
    printf("(%lf,%lf,%lf)\n",_x,_y,_z);
  }
};

class Line : public vector<Point> {
public:
  Line(const Point& p1,const Point& p2) {
    push_back(p1);
    push_back(p2);
  }
};

double norm(const Point& p){
  return sqrt(p._x * p._x + p._y * p._y + p._z * p._z);
}

Point unit(const Point& p){
  return p/norm(p);
}

double dot(const Point& p1,const Point& p2){
  return p1._x * p2._x + p1._y * p2._y + p1._z * p2._z;
}

Point cross(const Point& p1,const Point& p2){
  return Point(p1._y * p2._z - p1._z * p2._y,
               p1._z * p2._x - p1._x * p2._z,
               p1._x * p2._y - p1._y * p2._x);
}

Point projection(const Line& l,const Point& p){
  double t = dot(p - l[0],l[0]-l[1]) / norm(l[0] - l[1]);
  return l[0] + unit(l[0] - l[1]) * t;
}

bool EQ(const Point& s,const Point& t) {
  if((t._x - EPS <= s._x && s._x <= t._x + EPS)
     && (t._y - EPS <= s._y && s._y <= t._y + EPS)
     && (t._z - EPS <= s._z && s._z <= t._z + EPS)) return true;
  return false;
}

bool parallelLL(const Line &l, const Line &m) {
  return EQ(cross(l[1]-l[0], m[1]-m[0]),Point(0,0,0));
}

bool intersectLP(const Line &l, const Point &p) {
  return (norm(cross(l[1]-p, l[0]-p)) < EPS);
}

double distanceLP(const Line& l,const Point& p){
  if(intersectLP(l,p)) return 0;
  return norm(p - projection(l,p));
}

double distanceLL(const Line& l,const Line& m){
  if(parallelLL(l,m)) return distanceLP(l,m[0]);

  Point V1 = l[1] - l[0];
  Point V2 = m[1] - m[0];
  Point V3 = m[0]-l[0];
  double dist = abs(dot(cross(V1,V2),V3)/norm(cross(V1,V2)));
  return dist;
}

double dp[105][105];

int main(){
  int num_of_straight_paths;
  while(~scanf("%d",&num_of_straight_paths)){
    if(num_of_straight_paths == 0) break;

    double sx,sy,sz;
    double gx,gy,gz;
    scanf("%lf %lf %lf",&sx,&sy,&sz);
    scanf("%lf %lf %lf",&gx,&gy,&gz);
    
    vector<Line> lines;
    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      double x[2],y[2],z[2];
      for(int i = 0; i < 2; i++){
        scanf("%lf %lf %lf",&x[i],&y[i],&z[i]);
      }
      lines.push_back(Line(Point(x[0],y[0],z[0]),
                           Point(x[1],y[1],z[1])));

    }

    memset(dp,0,sizeof(dp));

    dp[0][num_of_straight_paths+1] 
      = dp[num_of_straight_paths+1][0]
      = norm(Point(sx,sy,sz) - Point(gx,gy,gz));

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[0][path_i + 1]
        = dp[path_i + 1][0]
        = distanceLP(lines[path_i],Point(sx,sy,sz));
      // printf("s to... %d %lf\n",path_i + 1,dp[0][path_i+1]);
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      dp[num_of_straight_paths + 1][path_i + 1]
        = dp[path_i + 1][num_of_straight_paths + 1]
        = distanceLP(lines[path_i],Point(gx,gy,gz));
      // printf("g to... %d %lf\n",path_i + 1,dp[path_i + 1][num_of_straight_paths + 1]);
    }

    for(int path_i = 0; path_i < num_of_straight_paths; path_i++){
      for(int path_j = path_i + 1; path_j < num_of_straight_paths; path_j++){
        dp[path_i + 1][path_j + 1]
          = dp[path_j + 1][path_i + 1]
          = distanceLL(lines[path_i],lines[path_j]);
        // printf("LL %d %d %lf\n",path_i + 1,path_j + 1,distanceLL(lines[path_i],lines[path_j]));
      }
    }

    for(int k=0;k<=num_of_straight_paths+1;k++){
      for(int i=0;i<=num_of_straight_paths+1;i++){
        for(int j=0;j<=num_of_straight_paths+1;j++){
          dp[i][j] = min(dp[i][k] + dp[k][j],dp[i][j]);
        }
      }
    }

    // for(int i=0;i<=num_of_straight_paths+1;i++){
    //   for(int j=i+1;j<=num_of_straight_paths+1;j++){
    //         printf("%d %d %lf\n",i,j,dp[i][j]);
    //   }
    // }

    printf("%lf\n",dp[0][num_of_straight_paths+1]);
  }
}
accuracy: 1
time_ms: 70
memory_kb: 1356
final_rank: 5

code_snippet: #include<bits/stdc++.h>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b))<EPS)
 
using namespace std;
 
//作成中 VerifyしたものにはVerifyと書いてある
 
//Verify AOJ 0115
class Point3d{
public:
  double x,y,z;
 
  Point3d(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
 
  Point3d operator + (const Point3d& a){
    return Point3d(x+a.x,y+a.y,z+a.z);
  }
  Point3d operator - (const Point3d& a){
    return Point3d(x-a.x,y-a.y,z-a.z);
  }
  Point3d operator * (const double& d){
    return Point3d(x*d,y*d,z*d);
  }
  Point3d operator / (const double& d){
    return Point3d(x/d,y/d,z/d);
  }
 
  bool operator < (const Point3d& p)const{
    return !equals(x,p.x)?x<p.x:((!equals(y,p.y))?y<p.y:z<p.z);
  }
 
  bool operator == (const Point3d& p)const{
    return equals(x,p.x) && equals(y,p.y) && equals(z,p.z);
  }
 
};
 
//Verify AOJ 0115
struct Segment3d{
  Point3d p[2];
  Segment3d(Point3d p1=Point3d(),Point3d p2=Point3d()){
    p[0] = p1, p[1] = p2;
  }
  bool operator == (const Segment3d& seg)const{
    return p[0] == seg.p[0] && p[1] == seg.p[1];
  }
};
 
typedef Point3d Vector3d;
typedef Segment3d Line3d;
 
 
 
 
ostream& operator << (ostream& os,const Point3d& p){
  os << "(" << p.x << "," << p.y << "," << p.z << ")";
}
 
ostream& operator << (ostream& os,const Segment3d& seg){
  os << "(" << seg.p[0] << "," << seg.p[1] << ")";
}
 
//Verify AOJ 0115
double dot(const Point3d& a,const Point3d& b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}
 
//Verify AOJ 0115
Vector3d cross(const Point3d& a,const Point3d& b){
  return Vector3d(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
 
//Verify AOJ 0115
inline double norm(const Point3d &p){
  return p.x*p.x + p.y*p.y + p.z*p.z;
}
 
//Verify AOJ 0115
inline double abs(const Point3d &p){
  return sqrt(norm(p));
}
 
inline double toRad(double theta){
  return theta * M_PI / 180.0;
}
 
 
 
bool on_line3d(Line3d line,Point3d p){
  return equals(abs(cross(p-line.p[0],line.p[1]-line.p[0])),0);
}
 
bool on_segment3d(Segment3d seg,Point3d p){
  if( !on_line3d(seg,p) ) return false;
  double dist[3] = { abs(seg.p[1]-seg.p[0]), abs(p-seg.p[0]), abs(p-seg.p[1]) };  
  return on_line3d(seg,p) && equals(dist[0],dist[1]+dist[2]);
}
 
//Verify AOJ 0115
bool point_on_the_triangle3d(Point3d tri1,Point3d tri2,Point3d tri3,Point3d p){
 
  //線分上にpがあった場合、三角形内とみなす
  //if( on_segment3d(Segment3d(tri1,tri2),p) ) return true;
  //if( on_segment3d(Segment3d(tri2,tri3),p) ) return true;
  //if( on_segment3d(Segment3d(tri3,tri1),p) ) return true;
 
  Vector3d v1 = tri2 - tri1;
  Vector3d v2 = tri3 - tri2;
  Vector3d v3 = tri1 - tri3;
 
  Vector3d cp[3] = { cross(v1,p-tri1), cross(v2,p-tri2), cross(v3,p-tri3) };
  double d1 = dot(cp[0],cp[1]);
  double d2 = dot(cp[0],cp[2]);
 
  // 線分上にpがあった場合,三角形内とはみなさない
  //if( ( !equals(d1,0.0) && d1 > 0 ) && ( !equals(d2,0.0) && d2 > 0 ) ) return true;
 
  // 線分上にpがあった場合,三角形内とみなす
  if( ( equals(d1,0.0) || d1 > 0 ) && ( equals(d2,0.0) || d2 > 0 ) ) return true;
  return false;
}
 
inline Point3d rotateX(Point3d p,double rad){
  return Point3d(p.x,p.y*cos(rad)-p.z*sin(rad),p.y*sin(rad)+p.z*cos(rad));
}
 
inline Point3d rorateY(Point3d p,double rad){
  return Point3d(p.x*cos(rad)+p.z*sin(rad),p.y,-p.x*sin(rad)+p.z*cos(rad));
}
 
inline Point3d rorateZ(Point3d p,double rad){
  return Point3d(p.x*cos(rad)-p.y*sin(rad),p.x*sin(rad)+p.y*cos(rad),p.z);
}
 
inline Point3d rotateEuler(Point3d p,double alpha,double beta,double gamma){
  return Point3d( (cos(alpha)*cos(beta)*cos(gamma)-sin(alpha)*sin(gamma)) * p.x + (-cos(alpha)*cos(beta)*sin(gamma)-sin(alpha)*cos(gamma)) * p.y + (cos(alpha)*sin(beta)) * p.z,
		  (sin(alpha)*cos(beta)*cos(gamma)+cos(alpha)*sin(gamma)) * p.x + (-sin(alpha)*cos(beta)*sin(gamma)+cos(alpha)*cos(gamma)) * p.y + (sin(alpha)*sin(beta)) * p.z,
		  (-sin(beta)*cos(gamma)) * p.x + (sin(beta)*sin(gamma)) * p.y + (cos(beta)) * p.z);
}
 
inline Point3d rotateRollPitchYaw(Point3d p,double roll,double pitch,double yaw){
  return Point3d( ( cos(roll) * cos(pitch) ) * p.x + ( cos(roll) * sin(pitch) * sin(yaw) - sin(roll) * cos(yaw) ) * p.y + ( cos(roll) * sin(pitch) * cos(yaw) + sin(roll) * sin(yaw) ) * p.z,
		  ( sin(roll) * cos(pitch) ) * p.x + ( sin(roll) * sin(pitch) * sin(yaw) + cos(roll) * cos(yaw) ) * p.y + ( sin(roll) * sin(pitch) * cos(yaw) - cos(roll) * sin(yaw) ) * p.z,
		  -sin(pitch) * p.x + cos(pitch) * sin(yaw) * p.y + cos(pitch) * cos(yaw) * p.z);
}
 
 
class Plane3d{
public:
  Point3d normal_vector; //法線ベクトル
  double d; // 平面方程式 normal_vector.x * x + normal_vector.y * y + normal_vector.z * z + d = 0
 
  Plane3d(Point3d normal_vector=Point3d(),double d=0):normal_vector(normal_vector),d(d){}
  Plane3d(Vector3d a,Vector3d b,Vector3d c){
    Vector3d v1 = b - a;
    Vector3d v2 = c - a;
    Vector3d tmp = cross(v1,v2);
    normal_vector = tmp / abs(tmp);
    set_d(a);
  }
 
  //Verify AOJ 0115
  //法線ベクトルnormal_vectorと平面上の１点からdを計算する
  void set_d(Point3d p){
    d = dot(normal_vector,p);
  }
 
  //平面と点pの距離を求める
  double distanceP(Point3d p){
    Point3d a = normal_vector * d;//平面上の適当な点をつくる
    return abs( dot(p-a,normal_vector) );
  }
 
  //平面上でもっとも点pと近い点を求める
  Point3d nearest_point(Point3d p){
    Point3d a = normal_vector * d;
    return p - ( normal_vector * dot(p-a,normal_vector) );
  }
 
  //Verify AOJ 0115
  //平面と線分が交差するか
  bool intersectS(Segment3d seg){
    Point3d a = normal_vector * d;
    double res1 = dot(a-seg.p[0],normal_vector);
    double res2 = dot(a-seg.p[1],normal_vector);
    if( res1 > res2 ) swap(res1,res2);
    //cout << res1 << " < " << res2 << endl;
    if( ( equals(res1,0.0) || res1 < 0 ) && ( equals(res2,0.0) || res2 > 0 ) ) return true;
    return false;
  }
 
  //Verify AOJ 0115
  //平面と線分の交点を求める
  Point3d crosspointS(Segment3d seg){
    Point3d a = normal_vector * d;
    double dot_p0a = fabs(dot( seg.p[0]-a,normal_vector ));
    double dot_p1a = fabs(dot( seg.p[1]-a,normal_vector ));
    if( equals(dot_p0a+dot_p1a,0) ) return seg.p[0];
    return seg.p[0] + ( seg.p[1] - seg.p[0] ) * ( dot_p0a / ( dot_p0a + dot_p1a ) );
  }
 
};
 
double distanceLP(Line3d line,Point3d p){
  return abs(cross(line.p[1]-line.p[0],p-line.p[0])) / abs(line.p[1]-line.p[0]);
}
 
Point3d project(Segment3d seg,Point3d p){
  Vector3d base = seg.p[1] - seg.p[0];
  double t = dot(p-seg.p[0],base) / norm(base);
  return seg.p[0] + base * t;
}
 
Point3d reflect(Segment3d seg,Point3d p){
  return p + (project(seg,p)-p) * 2.0;
}

//Verify AOJ 2081
bool isParallel(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
  return equals(tmp,0.0);
}
 
//Verify AOJ 2081 
//l1,l2が平行な時には使用できないので注意
Segment3d nearest_segmentLL(Line3d l1,Line3d l2){
  assert(!isParallel(l1,l2)); // 平行な場合は使用不可
  // l1.p[0] = A, l1.p[1] = B, l2.p[0] = C, l2.p[1] = D
  Vector3d AB = l1.p[1] - l1.p[0];
  Vector3d CD = l2.p[1] - l2.p[0];
  Vector3d AC = l2.p[0] - l1.p[0];
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double d1 = (dot(n1,AC)-dot(n1,n2)*dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  double d2 = (dot(n1,n2)*dot(n1,AC)-dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  return Segment3d(l1.p[0]+n1*d1,l2.p[0]+n2*d2);
}
 
//Verify AOJ 2081
bool intersectLL(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
 
  //そもそもl1,l2が直線じゃない
  if( equals(abs(B-A),0.0) || equals(abs(D-C),0.0) ){
    /*
      この場合は注意
      そもそも与えられた線分が線分になっていないので、交差するかどうかは判定できない
    */
    return false;
  }
 
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
 
  if( equals(tmp,0.0) ) return 0; // 直線が平行
 
  Segment3d ns = nearest_segmentLL(l1,l2);
  if( ns.p[0] == ns.p[1] ) return true;
  return false;
}

bool intersectSS(Segment3d seg1,Segment3d seg2){
  if( isParallel(seg1,seg2) ) return false;
  Segment3d seg = nearest_segmentLL(seg1,seg2);
  if( !( seg.p[0] == seg.p[1] ) ) return false;
  Point3d cp = seg.p[1];
  return on_segment3d(seg1,cp) && on_segment3d(seg2,cp);
}
 
Line3d line[110];
Point3d source_p,sink_p;
int source,sink;
double fw[110][110];
 
int main(){
  int N;
  while(cin>>N,N){
    cin >> source_p.x >> source_p.y >> source_p.z >> sink_p.x >> sink_p.y >> sink_p.z;
 
    source = sink = -1;
    rep(i,N){
      rep(j,2)cin >> line[i].p[j].x >> line[i].p[j].y >> line[i].p[j].z;
      if( on_line3d(line[i],source_p) ) {
	assert( source == -1 );
	source = i;
      }
      if( on_line3d(line[i],sink_p) ) {
	assert( sink == -1 );
	sink = i;
      }
    }
    assert( source != -1 && sink != -1 );
 
    rep(i,N)rep(j,N)fw[i][j] = IINF;
    rep(i,N)REP(j,i,N){
      if( i == j ) fw[i][j] = 0;
      else if( isParallel(line[i],line[j]) ){
	double area = abs( cross(line[i].p[1]-line[i].p[0],line[j].p[1]-line[i].p[0]) ) ;
	fw[i][j] = fw[j][i] = area / abs(line[i].p[1]-line[i].p[0]);
      }else if(!intersectLL(line[i],line[j])){
	Segment3d seg = nearest_segmentLL(line[i],line[j]);
	fw[i][j] = fw[j][i] = abs(seg.p[1]-seg.p[0]);
      } 
    }
 
    rep(k,N)rep(i,N)rep(j,N)if(!equals(fw[i][k],IINF) && !equals(fw[k][j],IINF))fw[i][j] = min(fw[i][j],fw[i][k]+fw[k][j]);
    printf("%.4f\n",fw[source][sink]);
  }
  return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 1352
final_rank: 11

code_snippet: #include<bits/stdc++.h>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b))<EPS)
 
using namespace std;
 
//テ、ツスツ愿ヲツ按静、ツクツュ Verifyテ」ツ?療」ツ?淌」ツつづ」ツ?ョテ」ツ?ォテ」ツ?ッVerifyテ」ツ?ィテヲツ崢クテ」ツ??」ツ?ヲテ」ツ?づ」ツつ?
 
//Verify AOJ 0115
class Point3d{
public:
  double x,y,z;
 
  Point3d(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
 
  Point3d operator + (const Point3d& a){
    return Point3d(x+a.x,y+a.y,z+a.z);
  }
  Point3d operator - (const Point3d& a){
    return Point3d(x-a.x,y-a.y,z-a.z);
  }
  Point3d operator * (const double& d){
    return Point3d(x*d,y*d,z*d);
  }
  Point3d operator / (const double& d){
    return Point3d(x/d,y/d,z/d);
  }
 
  bool operator < (const Point3d& p)const{
    return !equals(x,p.x)?x<p.x:((!equals(y,p.y))?y<p.y:z<p.z);
  }
 
  bool operator == (const Point3d& p)const{
    return equals(x,p.x) && equals(y,p.y) && equals(z,p.z);
  }
 
};
 
//Verify AOJ 0115
struct Segment3d{
  Point3d p[2];
  Segment3d(Point3d p1=Point3d(),Point3d p2=Point3d()){
    p[0] = p1, p[1] = p2;
  }
  bool operator == (const Segment3d& seg)const{
    return p[0] == seg.p[0] && p[1] == seg.p[1];
  }
};
 
typedef Point3d Vector3d;
typedef Segment3d Line3d;
 
 
 
 
ostream& operator << (ostream& os,const Point3d& p){
  os << "(" << p.x << "," << p.y << "," << p.z << ")";
}
 
ostream& operator << (ostream& os,const Segment3d& seg){
  os << "(" << seg.p[0] << "," << seg.p[1] << ")";
}
 
//Verify AOJ 0115
double dot(const Point3d& a,const Point3d& b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}
 
//Verify AOJ 0115
Vector3d cross(const Point3d& a,const Point3d& b){
  return Vector3d(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
 
//Verify AOJ 0115
inline double norm(const Point3d &p){
  return p.x*p.x + p.y*p.y + p.z*p.z;
}
 
//Verify AOJ 0115
inline double abs(const Point3d &p){
  return sqrt(norm(p));
}
 
inline double toRad(double theta){
  return theta * M_PI / 180.0;
}
 
 
 
bool on_line3d(Line3d line,Point3d p){
  return equals(abs(cross(p-line.p[0],line.p[1]-line.p[0])),0);
}
 
bool on_segment3d(Segment3d seg,Point3d p){
  if( !on_line3d(seg,p) ) return false;
  double dist[3] = { abs(seg.p[1]-seg.p[0]), abs(p-seg.p[0]), abs(p-seg.p[1]) };  
  return on_line3d(seg,p) && equals(dist[0],dist[1]+dist[2]);
}
 
//Verify AOJ 0115
bool point_on_the_triangle3d(Point3d tri1,Point3d tri2,Point3d tri3,Point3d p){
 
  //テァツキツ堙・ツ按?、ツクツ甘」ツ?ォpテ」ツ?古」ツ?づ」ツ?」テ」ツ?淌・ツ?エテ・ツ青暗」ツ??、ツクツ嘉ィツァツ津・ツスツ「テ・ツ??」ツ?ィテ」ツ?ソテ」ツ?ェテ」ツ??
  //if( on_segment3d(Segment3d(tri1,tri2),p) ) return true;
  //if( on_segment3d(Segment3d(tri2,tri3),p) ) return true;
  //if( on_segment3d(Segment3d(tri3,tri1),p) ) return true;
 
  Vector3d v1 = tri2 - tri1;
  Vector3d v2 = tri3 - tri2;
  Vector3d v3 = tri1 - tri3;
 
  Vector3d cp[3] = { cross(v1,p-tri1), cross(v2,p-tri2), cross(v3,p-tri3) };
  double d1 = dot(cp[0],cp[1]);
  double d2 = dot(cp[0],cp[2]);
 
  // テァツキツ堙・ツ按?、ツクツ甘」ツ?ォpテ」ツ?古」ツ?づ」ツ?」テ」ツ?淌・ツ?エテ・ツ青?テ、ツクツ嘉ィツァツ津・ツスツ「テ・ツ??」ツ?ィテ」ツ?ッテ」ツ?ソテ」ツ?ェテ」ツ?陛」ツ?ェテ」ツ??
  //if( ( !equals(d1,0.0) && d1 > 0 ) && ( !equals(d2,0.0) && d2 > 0 ) ) return true;
 
  // テァツキツ堙・ツ按?、ツクツ甘」ツ?ォpテ」ツ?古」ツ?づ」ツ?」テ」ツ?淌・ツ?エテ・ツ青?テ、ツクツ嘉ィツァツ津・ツスツ「テ・ツ??」ツ?ィテ」ツ?ソテ」ツ?ェテ」ツ??
  if( ( equals(d1,0.0) || d1 > 0 ) && ( equals(d2,0.0) || d2 > 0 ) ) return true;
  return false;
}
 
inline Point3d rotateX(Point3d p,double rad){
  return Point3d(p.x,p.y*cos(rad)-p.z*sin(rad),p.y*sin(rad)+p.z*cos(rad));
}
 
inline Point3d rorateY(Point3d p,double rad){
  return Point3d(p.x*cos(rad)+p.z*sin(rad),p.y,-p.x*sin(rad)+p.z*cos(rad));
}
 
inline Point3d rorateZ(Point3d p,double rad){
  return Point3d(p.x*cos(rad)-p.y*sin(rad),p.x*sin(rad)+p.y*cos(rad),p.z);
}
 
inline Point3d rotateEuler(Point3d p,double alpha,double beta,double gamma){
  return Point3d( (cos(alpha)*cos(beta)*cos(gamma)-sin(alpha)*sin(gamma)) * p.x + (-cos(alpha)*cos(beta)*sin(gamma)-sin(alpha)*cos(gamma)) * p.y + (cos(alpha)*sin(beta)) * p.z,
		  (sin(alpha)*cos(beta)*cos(gamma)+cos(alpha)*sin(gamma)) * p.x + (-sin(alpha)*cos(beta)*sin(gamma)+cos(alpha)*cos(gamma)) * p.y + (sin(alpha)*sin(beta)) * p.z,
		  (-sin(beta)*cos(gamma)) * p.x + (sin(beta)*sin(gamma)) * p.y + (cos(beta)) * p.z);
}
 
inline Point3d rotateRollPitchYaw(Point3d p,double roll,double pitch,double yaw){
  return Point3d( ( cos(roll) * cos(pitch) ) * p.x + ( cos(roll) * sin(pitch) * sin(yaw) - sin(roll) * cos(yaw) ) * p.y + ( cos(roll) * sin(pitch) * cos(yaw) + sin(roll) * sin(yaw) ) * p.z,
		  ( sin(roll) * cos(pitch) ) * p.x + ( sin(roll) * sin(pitch) * sin(yaw) + cos(roll) * cos(yaw) ) * p.y + ( sin(roll) * sin(pitch) * cos(yaw) - cos(roll) * sin(yaw) ) * p.z,
		  -sin(pitch) * p.x + cos(pitch) * sin(yaw) * p.y + cos(pitch) * cos(yaw) * p.z);
}
 
 
class Plane3d{
public:
  Point3d normal_vector; //テヲツウツ陛ァツキツ堙」ツδ凖」ツつッテ」ツδ暗」ツδォ
  double d; // テ・ツケツウテゥツ敖「テヲツ鳴ケテァツィツ凝・ツシツ?normal_vector.x * x + normal_vector.y * y + normal_vector.z * z + d = 0
 
  Plane3d(Point3d normal_vector=Point3d(),double d=0):normal_vector(normal_vector),d(d){}
  Plane3d(Vector3d a,Vector3d b,Vector3d c){
    Vector3d v1 = b - a;
    Vector3d v2 = c - a;
    Vector3d tmp = cross(v1,v2);
    normal_vector = tmp / abs(tmp);
    set_d(a);
  }
 
  //Verify AOJ 0115
  //テヲツウツ陛ァツキツ堙」ツδ凖」ツつッテ」ツδ暗」ツδォnormal_vectorテ」ツ?ィテ・ツケツウテゥツ敖「テ、ツクツ甘」ツ?ョテッツシツ妥ァツつケテ」ツ?凝」ツつ嬰テ」ツつ津ィツィツ暗ァツョツ療」ツ?凖」ツつ?
  void set_d(Point3d p){
    d = dot(normal_vector,p);
  }
 
  //テ・ツケツウテゥツ敖「テ」ツ?ィテァツつケpテ」ツ?ョティツキツ敕ゥツ崢「テ」ツつ津ヲツアツづ」ツつ?」ツつ?
  double distanceP(Point3d p){
    Point3d a = normal_vector * d;//テ・ツケツウテゥツ敖「テ、ツクツ甘」ツ?ョテゥツ?ゥテ・ツスツ禿」ツ?ェテァツつケテ」ツつ津」ツ?、テ」ツ?湘」ツつ?
    return abs( dot(p-a,normal_vector) );
  }
 
  //テ・ツケツウテゥツ敖「テ、ツクツ甘」ツ?ァテ」ツつづ」ツ?」テ」ツ?ィテ」ツつづァツつケpテ」ツ?ィティツソツ妥」ツ??ァツつケテ」ツつ津ヲツアツづ」ツつ?」ツつ?
  Point3d nearest_point(Point3d p){
    Point3d a = normal_vector * d;
    return p - ( normal_vector * dot(p-a,normal_vector) );
  }
 
  //Verify AOJ 0115
  //テ・ツケツウテゥツ敖「テ」ツ?ィテァツキツ堙・ツ按?」ツ?古、ツコツ、テ・ツキツョテ」ツ?凖」ツつ凝」ツ??
  bool intersectS(Segment3d seg){
    Point3d a = normal_vector * d;
    double res1 = dot(a-seg.p[0],normal_vector);
    double res2 = dot(a-seg.p[1],normal_vector);
    if( res1 > res2 ) swap(res1,res2);
    //cout << res1 << " < " << res2 << endl;
    if( ( equals(res1,0.0) || res1 < 0 ) && ( equals(res2,0.0) || res2 > 0 ) ) return true;
    return false;
  }
 
  //Verify AOJ 0115
  //テ・ツケツウテゥツ敖「テ」ツ?ィテァツキツ堙・ツ按?」ツ?ョテ、ツコツ、テァツつケテ」ツつ津ヲツアツづ」ツつ?」ツつ?
  Point3d crosspointS(Segment3d seg){
    Point3d a = normal_vector * d;
    double dot_p0a = fabs(dot( seg.p[0]-a,normal_vector ));
    double dot_p1a = fabs(dot( seg.p[1]-a,normal_vector ));
    if( equals(dot_p0a+dot_p1a,0) ) return seg.p[0];
    return seg.p[0] + ( seg.p[1] - seg.p[0] ) * ( dot_p0a / ( dot_p0a + dot_p1a ) );
  }
 
};
 
double distanceLP(Line3d line,Point3d p){
  return abs(cross(line.p[1]-line.p[0],p-line.p[0])) / abs(line.p[1]-line.p[0]);
}
 
Point3d project(Segment3d seg,Point3d p){
  Vector3d base = seg.p[1] - seg.p[0];
  double t = dot(p-seg.p[0],base) / norm(base);
  return seg.p[0] + base * t;
}
 
Point3d reflect(Segment3d seg,Point3d p){
  return p + (project(seg,p)-p) * 2.0;
}
 
Segment3d nearest_segmentLL(Line3d l1,Line3d l2){
  // l1.p[0] = A, l1.p[1] = B, l2.p[0] = C, l2.p[1] = D
  Vector3d AB = l1.p[1] - l1.p[0];
  Vector3d CD = l2.p[1] - l2.p[0];
  Vector3d AC = l2.p[0] - l1.p[0];
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double d1 = (dot(n1,AC)-dot(n1,n2)*dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  double d2 = (dot(n1,n2)*dot(n1,AC)-dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  return Segment3d(l1.p[0]+n1*d1,l2.p[0]+n2*d2);
}
 
bool isParallel(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
  return equals(tmp,0.0);
}
 
bool intersectLL(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
 
  //テ」ツ?敕」ツつづ」ツ?敕」ツつＭ1,l2テ」ツ?古ァツ崢エテァツキツ堙」ツ?佚」ツつε」ツ?ェテ」ツ??
  if( equals(abs(B-A),0.0) || equals(abs(D-C),0.0) ){
    /*
      テ」ツ?禿」ツ?ョテ・ツ?エテ・ツ青暗」ツ?ッテヲツウツィテヲツ??
      テ」ツ?敕」ツつづ」ツ?敕」ツつづ、ツクツ偲」ツ?暗」ツつ嘉」ツつ古」ツ?淌ァツキツ堙・ツ按?」ツ?古ァツキツ堙・ツ按?」ツ?ォテ」ツ?ェテ」ツ?」テ」ツ?ヲテ」ツ??」ツ?ェテ」ツ??」ツ?ョテ」ツ?ァテ」ツ??、ツコツ、テ・ツキツョテ」ツ?凖」ツつ凝」ツ?凝」ツ?ゥテ」ツ??」ツ?凝」ツ?ッテ・ツ按、テ・ツョツ堙」ツ?ァテ」ツ?催」ツ?ェテ」ツ??
    */
    return false;
  }
 
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
 
  if( equals(tmp,0.0) ) return 0; // テァツ崢エテァツキツ堙」ツ?古・ツケツウティツ。ツ?
 
  Segment3d ns = nearest_segmentLL(l1,l2);
  if( ns.p[0] == ns.p[1] ) return true;
  return false;
}
 
Line3d line[110];
Point3d source_p,sink_p;
int source,sink;
double fw[110][110];
 
int main(){
  int N;
  while(cin>>N,N){
    cin >> source_p.x >> source_p.y >> source_p.z >> sink_p.x >> sink_p.y >> sink_p.z;
 
    source = sink = -1;
    rep(i,N){
      rep(j,2)cin >> line[i].p[j].x >> line[i].p[j].y >> line[i].p[j].z;
      if( on_line3d(line[i],source_p) ) {
	assert( source == -1 );
	source = i;
      }
      if( on_line3d(line[i],sink_p) ) {
	assert( sink == -1 );
	sink = i;
      }
    }
    assert( source != -1 && sink != -1 );
 
    rep(i,N)rep(j,N)fw[i][j] = IINF;
    rep(i,N)REP(j,i,N){
      if( i == j ) fw[i][j] = 0;
      else if( isParallel(line[i],line[j]) ){
	double area = abs( cross(line[i].p[1]-line[i].p[0],line[j].p[1]-line[i].p[0]) ) ;
	fw[i][j] = fw[j][i] = area / abs(line[i].p[1]-line[i].p[0]);
      }
      else if(!intersectLL(line[i],line[j])){
	Segment3d seg = nearest_segmentLL(line[i],line[j]);
	fw[i][j] = fw[j][i] = abs(seg.p[1]-seg.p[0]);
      } 
    }
 
    rep(k,N)rep(i,N)rep(j,N)if(!equals(fw[i][k],IINF) && !equals(fw[k][j],IINF))fw[i][j] = min(fw[i][j],fw[i][k]+fw[k][j]);
    printf("%.4f\n",fw[source][sink]);
  }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1352
final_rank: 10

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

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b))<EPS)

using namespace std;

//作成中 VerifyしたものにはVerifyと書いてある

//Verify AOJ 0115
class Point3d{
public:
  double x,y,z;

  Point3d(double x=0,double y=0,double z=0):x(x),y(y),z(z){}

  Point3d operator + (const Point3d& a){
    return Point3d(x+a.x,y+a.y,z+a.z);
  }
  Point3d operator - (const Point3d& a){
    return Point3d(x-a.x,y-a.y,z-a.z);
  }
  Point3d operator * (const double& d){
    return Point3d(x*d,y*d,z*d);
  }
  Point3d operator / (const double& d){
    return Point3d(x/d,y/d,z/d);
  }

  bool operator < (const Point3d& p)const{
    return !equals(x,p.x)?x<p.x:((!equals(y,p.y))?y<p.y:z<p.z);
  }

  bool operator == (const Point3d& p)const{
    return equals(x,p.x) && equals(y,p.y) && equals(z,p.z);
  }

};

//Verify AOJ 0115
struct Segment3d{
  Point3d p[2];
  Segment3d(Point3d p1=Point3d(),Point3d p2=Point3d()){
    p[0] = p1, p[1] = p2;
  }
  bool operator == (const Segment3d& seg)const{
    return p[0] == seg.p[0] && p[1] == seg.p[1];
  }
};

typedef Point3d Vector3d;
typedef Segment3d Line3d;




ostream& operator << (ostream& os,const Point3d& p){
  os << "(" << p.x << "," << p.y << "," << p.z << ")";
}

ostream& operator << (ostream& os,const Segment3d& seg){
  os << "(" << seg.p[0] << "," << seg.p[1] << ")";
}

//Verify AOJ 0115
double dot(const Point3d& a,const Point3d& b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}

//Verify AOJ 0115
Vector3d cross(const Point3d& a,const Point3d& b){
  return Vector3d(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}

//Verify AOJ 0115
inline double norm(const Point3d &p){
  return p.x*p.x + p.y*p.y + p.z*p.z;
}

//Verify AOJ 0115
inline double abs(const Point3d &p){
  return sqrt(norm(p));
}

inline double toRad(double theta){
  return theta * M_PI / 180.0;
}



bool on_line3d(Line3d line,Point3d p){
  return equals(abs(cross(p-line.p[0],line.p[1]-line.p[0])),0);
}

bool on_segment3d(Segment3d seg,Point3d p){
  if( !on_line3d(seg,p) ) return false;
  double dist[3] = { abs(seg.p[1]-seg.p[0]), abs(p-seg.p[0]), abs(p-seg.p[1]) };  
  return on_line3d(seg,p) && equals(dist[0],dist[1]+dist[2]);
}

//Verify AOJ 0115
bool point_on_the_triangle3d(Point3d tri1,Point3d tri2,Point3d tri3,Point3d p){

  //線分上にpがあった場合、三角形内とみなす
  //if( on_segment3d(Segment3d(tri1,tri2),p) ) return true;
  //if( on_segment3d(Segment3d(tri2,tri3),p) ) return true;
  //if( on_segment3d(Segment3d(tri3,tri1),p) ) return true;

  Vector3d v1 = tri2 - tri1;
  Vector3d v2 = tri3 - tri2;
  Vector3d v3 = tri1 - tri3;

  Vector3d cp[3] = { cross(v1,p-tri1), cross(v2,p-tri2), cross(v3,p-tri3) };
  double d1 = dot(cp[0],cp[1]);
  double d2 = dot(cp[0],cp[2]);

  // 線分上にpがあった場合,三角形内とはみなさない
  //if( ( !equals(d1,0.0) && d1 > 0 ) && ( !equals(d2,0.0) && d2 > 0 ) ) return true;

  // 線分上にpがあった場合,三角形内とみなす
  if( ( equals(d1,0.0) || d1 > 0 ) && ( equals(d2,0.0) || d2 > 0 ) ) return true;
  return false;
}

inline Point3d rotateX(Point3d p,double rad){
  return Point3d(p.x,p.y*cos(rad)-p.z*sin(rad),p.y*sin(rad)+p.z*cos(rad));
}

inline Point3d rorateY(Point3d p,double rad){
  return Point3d(p.x*cos(rad)+p.z*sin(rad),p.y,-p.x*sin(rad)+p.z*cos(rad));
}

inline Point3d rorateZ(Point3d p,double rad){
  return Point3d(p.x*cos(rad)-p.y*sin(rad),p.x*sin(rad)+p.y*cos(rad),p.z);
}

inline Point3d rotateEuler(Point3d p,double alpha,double beta,double gamma){
  return Point3d( (cos(alpha)*cos(beta)*cos(gamma)-sin(alpha)*sin(gamma)) * p.x + (-cos(alpha)*cos(beta)*sin(gamma)-sin(alpha)*cos(gamma)) * p.y + (cos(alpha)*sin(beta)) * p.z,
		  (sin(alpha)*cos(beta)*cos(gamma)+cos(alpha)*sin(gamma)) * p.x + (-sin(alpha)*cos(beta)*sin(gamma)+cos(alpha)*cos(gamma)) * p.y + (sin(alpha)*sin(beta)) * p.z,
		  (-sin(beta)*cos(gamma)) * p.x + (sin(beta)*sin(gamma)) * p.y + (cos(beta)) * p.z);
}

inline Point3d rotateRollPitchYaw(Point3d p,double roll,double pitch,double yaw){
  return Point3d( ( cos(roll) * cos(pitch) ) * p.x + ( cos(roll) * sin(pitch) * sin(yaw) - sin(roll) * cos(yaw) ) * p.y + ( cos(roll) * sin(pitch) * cos(yaw) + sin(roll) * sin(yaw) ) * p.z,
		  ( sin(roll) * cos(pitch) ) * p.x + ( sin(roll) * sin(pitch) * sin(yaw) + cos(roll) * cos(yaw) ) * p.y + ( sin(roll) * sin(pitch) * cos(yaw) - cos(roll) * sin(yaw) ) * p.z,
		  -sin(pitch) * p.x + cos(pitch) * sin(yaw) * p.y + cos(pitch) * cos(yaw) * p.z);
}


class Plane3d{
public:
  Point3d normal_vector; //法線ベクトル
  double d; // 平面方程式 normal_vector.x * x + normal_vector.y * y + normal_vector.z * z + d = 0

  Plane3d(Point3d normal_vector=Point3d(),double d=0):normal_vector(normal_vector),d(d){}
  Plane3d(Vector3d a,Vector3d b,Vector3d c){
    Vector3d v1 = b - a;
    Vector3d v2 = c - a;
    Vector3d tmp = cross(v1,v2);
    normal_vector = tmp / abs(tmp);
    set_d(a);
  }

  //Verify AOJ 0115
  //法線ベクトルnormal_vectorと平面上の１点からdを計算する
  void set_d(Point3d p){
    d = dot(normal_vector,p);
  }

  //平面と点pの距離を求める
  double distanceP(Point3d p){
    Point3d a = normal_vector * d;//平面上の適当な点をつくる
    return abs( dot(p-a,normal_vector) );
  }

  //平面上でもっとも点pと近い点を求める
  Point3d nearest_point(Point3d p){
    Point3d a = normal_vector * d;
    return p - ( normal_vector * dot(p-a,normal_vector) );
  }

  //Verify AOJ 0115
  //平面と線分が交差するか
  bool intersectS(Segment3d seg){
    Point3d a = normal_vector * d;
    double res1 = dot(a-seg.p[0],normal_vector);
    double res2 = dot(a-seg.p[1],normal_vector);
    if( res1 > res2 ) swap(res1,res2);
    //cout << res1 << " < " << res2 << endl;
    if( ( equals(res1,0.0) || res1 < 0 ) && ( equals(res2,0.0) || res2 > 0 ) ) return true;
    return false;
  }

  //Verify AOJ 0115
  //平面と線分の交点を求める
  Point3d crosspointS(Segment3d seg){
    Point3d a = normal_vector * d;
    double dot_p0a = fabs(dot( seg.p[0]-a,normal_vector ));
    double dot_p1a = fabs(dot( seg.p[1]-a,normal_vector ));
    if( equals(dot_p0a+dot_p1a,0) ) return seg.p[0];
    return seg.p[0] + ( seg.p[1] - seg.p[0] ) * ( dot_p0a / ( dot_p0a + dot_p1a ) );
  }

};

double distanceLP(Line3d line,Point3d p){
  return abs(cross(line.p[1]-line.p[0],p-line.p[0])) / abs(line.p[1]-line.p[0]);
}

Point3d project(Segment3d seg,Point3d p){
  Vector3d base = seg.p[1] - seg.p[0];
  double t = dot(p-seg.p[0],base) / norm(base);
  return seg.p[0] + base * t;
}

Point3d reflect(Segment3d seg,Point3d p){
  return p + (project(seg,p)-p) * 2.0;
}

Segment3d nearest_segmentLL(Line3d l1,Line3d l2){
  // l1.p[0] = A, l1.p[1] = B, l2.p[0] = C, l2.p[1] = D
  Vector3d AB = l1.p[1] - l1.p[0];
  Vector3d CD = l2.p[1] - l2.p[0];
  Vector3d AC = l2.p[0] - l1.p[0];
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double d1 = (dot(n1,AC)-dot(n1,n2)*dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  double d2 = (dot(n1,n2)*dot(n1,AC)-dot(n2,AC)) / (1.0-pow(dot(n1,n2),2));
  return Segment3d(l1.p[0]+n1*d1,l2.p[0]+n2*d2);
}

bool isParallel(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];
  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;
  return equals(tmp,0.0);
}

bool intersectLL(Line3d l1,Line3d l2){
  Vector3d A = l1.p[0], B = l1.p[1], C = l2.p[0], D = l2.p[1];

  //そもそもl1,l2が直線じゃない
  if( equals(abs(B-A),0.0) || equals(abs(D-C),0.0) ){
    /*
      この場合は注意
      そもそも与えられた線分が線分になっていないので、交差するかどうかは判定できない
     */
    return false;
  }

  Vector3d AB = B - A, CD = D - C;
  Vector3d n1 = AB / abs(AB), n2 = CD / abs(CD);
  double tmp = dot(n1,n2);
  tmp = 1 - tmp*tmp;

  if( equals(tmp,0.0) ) return 0; // 直線が平行

  Segment3d ns = nearest_segmentLL(l1,l2);
  if( ns.p[0] == ns.p[1] ) return true;
  return false;
}

Line3d line[110];
Point3d source_p,sink_p;
int source,sink;
double fw[110][110];

int main(){
  int N;
  while(cin>>N,N){
    cin >> source_p.x >> source_p.y >> source_p.z >> sink_p.x >> sink_p.y >> sink_p.z;

    source = sink = -1;
    rep(i,N){
      rep(j,2)cin >> line[i].p[j].x >> line[i].p[j].y >> line[i].p[j].z;
      if( on_line3d(line[i],source_p) ) {
	assert( source == -1 );
	source = i;
      }
      if( on_line3d(line[i],sink_p) ) {
	assert( sink == -1 );
	sink = i;
      }
    }
    assert( source != -1 && sink != -1 );

    rep(i,N)rep(j,N)fw[i][j] = IINF;
    rep(i,N)REP(j,i,N){
      if( i == j ) fw[i][j] = 0;
      else if( isParallel(line[i],line[j]) ){
	double area = abs( cross(line[i].p[1]-line[i].p[0],line[j].p[1]-line[i].p[0]) ) ;
	fw[i][j] = fw[j][i] = area / abs(line[i].p[1]-line[i].p[0]);
      }
      else if(!intersectLL(line[i],line[j])){
	Segment3d seg = nearest_segmentLL(line[i],line[j]);
	fw[i][j] = fw[j][i] = abs(seg.p[1]-seg.p[0]);
      } 

    }

    rep(k,N)rep(i,N)rep(j,N)if(!equals(fw[i][k],IINF) && !equals(fw[k][j],IINF))fw[i][j] = min(fw[i][j],fw[i][k]+fw[k][j]);
    printf("%.4f\n",fw[source][sink]);
  }
  return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 1352
final_rank: 11

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef valarray<double> point;
struct line : public vector<point> {
  line() {}
  line(point a, point b) { push_back(a); push_back(b); }
  point v() const { return (*this)[1]-(*this)[0]; }
};
point Point(double x, double y, double z) {
  point p(3);
  p[0]=x;p[1]=y;p[2]=z;
  return p;
}
double dot(const point& a, const point& b) {
  return (a * b).sum();
}
point cross(const point& a, const point& b) {
  return a.cshift(+1)*b.cshift(-1)
       - a.cshift(-1)*b.cshift(+1);
}
double norm(const point &a) {
  return dot(a,a);
}
double length(const point &a) {
  return sqrt(dot(a,a));
}
double angle(const point &a, const point &b) {
  return acos( dot(a,b)/length(a)/length(b) );
}
point input() {
  double a[3];
  REP(i,3) cin >>a[i];
  return point(a,3);
}
ostream &operator<<(ostream &os, const point &a) {
  char str[200];
  snprintf(str, 199, "(%.2f, %.2f, %.2f)", a[0], a[1], a[2]);
  os << str;
  return os;
}

point projection(const line &l, const point &p) {
  double t = dot(p-l[0], l.v()) / norm(l.v());
  return l[0] + t * l.v();
}
bool intersectSP(const line &s, const point &p) {
  return length(s[0]-p) + length(s[1]-p) - length(s[1]-s[0]) < EPS;
}
double distanceLP(const line &l, const point &p) {
  const point r = projection(l,p);
  return length(r-p);
}
double distanceSP(const line &s, const point &p) {
  const point r = projection(s, p);
  if (intersectSP(s, r)) { return length(r-p); }
  return min(length(s[0]-p), length(s[1]-p));
}

int crosspointPlL(const point &p, const point &n, const line &l, point &res) {
  double d = dot(n,l.v());
  if (abs(d) < EPS) return 0;
  double t = -dot(n,l[0]-p) / d;
  res = l[0]+t*l.v();
  return t>-EPS?1:-1;
}

// AOJ2081?
double distanceLL(const line &l, const line &m) {
  point n = cross(l.v(),m.v());
  return abs(dot(n,l[0]-m[0]))/length(n);
}

double dist[102][102];

int main() {
  int n;
  while(cin >> n, n) {
    point ps(input());
    point pt(input());
    vector<line> ls;
    REP(i,n) {
      point a(input());
      point b(input());
      ls.push_back(line(a,b));
    }
    dist[n][n] = dist[n+1][n+1] = 0;
    dist[n][n+1] = dist[n+1][n] = INF;
    REP(i,n) {
      dist[i][n] = dist[n][i] = distanceLP(ls[i],ps);
      dist[i][n+1] = dist[n+1][i] = distanceLP(ls[i],pt);
      REP(j,n) {
        dist[i][j] = distanceLL(ls[i],ls[j]);
      }
    }
    n += 2;
    REP(k,n)REP(i,n)REP(j,n) {
      chmin(dist[i][j],dist[i][k]+dist[k][j]);
    }
    printf("%.10f\n", dist[n-2][n-1]);
  }
}
accuracy: 1
time_ms: 250
memory_kb: 1364
final_rank: 16

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#define REP(i,n) for(int i=0;i<(int)n;++i)
#ifdef __GNUC__
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T val){
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  val = (val + (val >> 4)) & 0x0f0f0f0f;
  val += val >> 8;
  val += val >> 16;
  return (int)(val & 0x0000003f);
}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> void PrintSeq(T &a,int sz){for(int i=0;i<sz;i++){cout<<a[i];if(sz==i+1)cout<<endl;else cout<<' ';}}
ll getTen(int a){return (a<=0)?1:(getTen(a-1)*10);}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}

int N;
double sy,sx,sz;
double gy,gx,gz;
double px[101][2];
double py[101][2];
double pz[101][2];
double d[101][101];

struct Point{
  double x,y,z;
  Point(){}
  Point(double x_,double y_,double z_){
    x=x_,y=y_,z=z_;
  }
  Point operator-(const Point &p)const{
    return Point(x-p.x,y-p.y,z-p.z);
  }
  Point operator+(const Point &p)const{
    return Point(x+p.x,y+p.y,z+p.z);
  }
  Point operator/(double d)const{
    return Point(x/d,y/d,z/d);
  }
  string ToString(){
    string res;
    {
      stringstream ss;
      ss<<x;
      res+=ss.str();
    }
    res+=' ';
    {
      stringstream ss;
      ss<<y;
      res+=ss.str();
    }
    res+=' ';
    {
      stringstream ss;
      ss<<z;
      res+=ss.str();
    }
    return res;
  }
};

double dot(Point p1,Point p2){
  return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
Point cross(Point p1,Point p2){
  return Point(p1.y*p2.z-p1.z*p2.y,p1.z*p2.x-p1.x*p2.z,p1.x*p2.y-p1.y*p2.x);
}
double abs(Point p){
  return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}

double calcDist(Point p1,Point p2,Point p3,Point p4){
  Point n=cross(p2-p1,p4-p3);
  Point c=(p3-p1);
  if(!EQ(abs(n),0))return abs(dot(n,c))/abs(n);
  else {
    Point x=p3-p1;
    Point y=(p2-p1)/abs(p2-p1);
    return abs(cross(x,y));
  }
}

int main(){

  while(cin>>N&&N){
    cin>>sx>>sy>>sz>>gx>>gy>>gz;
    for(int i=0;i<N;i++)
      for(int j=0;j<2;j++)
        cin>>px[i][j]>>py[i][j]>>pz[i][j];
    for(int i=0;i<N;i++){
      for(int j=i;j<N;j++){
        if(i==j)d[i][j]=0;
        else d[i][j]=d[j][i]=calcDist(Point(px[i][0],py[i][0],pz[i][0])
                                      ,Point(px[i][1],py[i][1],pz[i][1])
                                      ,Point(px[j][0],py[j][0],pz[j][0])
                                      ,Point(px[j][1],py[j][1],pz[j][1]));
      }
    }
    for(int k=0;k<N;k++)
      for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
          d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    int spos=-1,gpos=-1;
    for(int i=0;i<N;i++){
      if(EQ(0,calcDist(Point(px[i][0],py[i][0],pz[i][0]),Point(px[i][1],py[i][1],pz[i][1])
                       ,Point(sx,sy,sz),Point(sx,sy,sz))))spos=i;
      if(EQ(0,calcDist(Point(px[i][0],py[i][0],pz[i][0]),Point(px[i][1],py[i][1],pz[i][1])
                       ,Point(gx,gy,gz),Point(gx,gy,gz))))gpos=i;
    }
    printf("%.10f\n",d[spos][gpos]);
  }
  
  
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 1336
final_rank: 6

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#define REP(i,n) for(int i=0;i<(int)n;++i)
#ifdef __GNUC__
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T val){
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  val = (val + (val >> 4)) & 0x0f0f0f0f;
  val += val >> 8;
  val += val >> 16;
  return (int)(val & 0x0000003f);
}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> void PrintSeq(T &a,int sz){for(int i=0;i<sz;i++){cout<<a[i];if(sz==i+1)cout<<endl;else cout<<' ';}}
ll getTen(int a){return (a<=0)?1:(getTen(a-1)*10);}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}

int N;
double sy,sx,sz;
double gy,gx,gz;
double px[101][2];
double py[101][2];
double pz[101][2];
double d[101][101];

struct Point{
  double x,y,z;
  Point(){}
  Point(double x_,double y_,double z_){
    x=x_,y=y_,z=z_;
  }
  Point operator-(const Point &p)const{
    return Point(x-p.x,y-p.y,z-p.z);
  }
  Point operator+(const Point &p)const{
    return Point(x+p.x,y+p.y,z+p.z);
  }
  Point operator/(double d)const{
    return Point(x/d,y/d,z/d);
  }
  string ToString(){
    string res;
    {
      stringstream ss;
      ss<<x;
      res+=ss.str();
    }
    res+=' ';
    {
      stringstream ss;
      ss<<y;
      res+=ss.str();
    }
    res+=' ';
    {
      stringstream ss;
      ss<<z;
      res+=ss.str();
    }
    return res;
  }
};

double dot(Point p1,Point p2){
  return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
Point cross(Point p1,Point p2){
  return Point(p1.y*p2.z-p1.z*p2.y,p1.z*p2.x-p1.x*p2.z,p1.x*p2.y-p1.y*p2.x);
}
double abs(Point p){
  return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}

double calcDist(Point p1,Point p2,Point p3,Point p4){
  Point n=cross(p2-p1,p4-p3);
  Point c=(p3-p1);
  // cout<<p1.ToString()<<endl;
  // cout<<p2.ToString()<<endl;
  // cout<<p3.ToString()<<endl;
  // cout<<p4.ToString()<<endl;
  //cout<<n.ToString()<<endl;
  // cout<<n.x<<" "<<n.y<<" "<<n.z<<endl;
  // cout<<abs(n)<<endl;
  if(!EQ(abs(n),0))return abs(dot(n,c))/abs(n);
  else {
    Point x=p3-p1;
    Point y=(p2-p1)/abs(p2-p1);
    return abs(cross(x,y));
  }
}

// 線分と点の間の距離を計算(3次元)
double calcDist(double x0,double y0,double z0,double x1,double y1,double z1,double px,double py,double pz){
  double res=0;
  double dy=y1-y0;
  double dz=z1-z0;
  double dx=x1-x0;
  double a=dx*dx+dy*dy+dz*dz;
  double b=dx*x0+dy*y0+dz*z0;
  double c=(dx*px+dy*py+dz*pz);
  double t=0;
  if(!EQ(a,0))t=(c-b)/a;
  double ox=x0+dx*t;
  double oy=y0+dy*t;
  double oz=z0+dz*t;
  res=sqrt((ox-px)*(ox-px)+(oy-py)*(oy-py)+(oz-pz)*(oz-pz));
  return res;
}


double calcDist(double x0,double y0,double z0,double x1,double y1,double z1
                ,double x2,double y2,double z2,double x3,double y3,double z3){
  double res=0;
  double a1=(x3-x2)*(x1-x0)+(y3-y2)*(y1-y0)+(z3-z2)*(z1-z0);
  double a2=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)+(z1-z0)*(z1-z0);
  double a3=(x1-x0)*(x2-x0)+(y1-y0)*(y2-y0)+(z1-z0)*(z2-z0);
  double b1=(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)+(z3-z2)*(z3-z2);
  double b2=(x1-x0)*(x3-x2)+(y1-y0)*(y3-y2)+(z1-z0)*(z3-z2);
  double b3=(x3-x2)*(x2-x0)+(y3-y2)*(y2-y0)+(z3-z2)*(z2-z0);
  double t,s;
  if(a1==0){
    t=a3/a2;
    s=(t*b2-b3)/b1;
  }
  else if(a2==0){
    s=-a3/a1;
    t=(s*b1+b3)/b2;
  }
  else if(b1==0){
    t=b3/b2;
    s=(t*a2-a3)/a1;
  }
  else if(b2==0){
    s=-b3/b1;
    t=(s*a1+a3)/a2;
  }
  else{
    if(a2*b1-a1*b2==0)t=0;
    else t=(a3*b1-a1*b3)/(a2*b1-a1*b2);
    s=(t*a2-a3)/a1;
  }
  
  double p1x=x0+t*(x1-x0);
  double p1y=y0+t*(y1-y0);
  double p1z=z0+t*(z1-z0);

  double p2x=x2+s*(x3-x2);
  double p2y=y2+s*(y3-y2);
  double p2z=z2+s*(z3-z2);

  res=sqrt((p1x-p2x)*(p1x-p2x)+(p1y-p2y)*(p1y-p2y)+(p1z-p2z)*(p1z-p2z));
  
  return res;
}

int main(){

  while(cin>>N&&N){
    cin>>sx>>sy>>sz>>gx>>gy>>gz;
    for(int i=0;i<N;i++)
      for(int j=0;j<2;j++)
        cin>>px[i][j]>>py[i][j]>>pz[i][j];
    for(int i=0;i<N;i++){
      for(int j=i;j<N;j++){
        if(i==j)d[i][j]=0;
        else d[i][j]=d[j][i]=calcDist(Point(px[i][0],py[i][0],pz[i][0])
                                      ,Point(px[i][1],py[i][1],pz[i][1])
                                      ,Point(px[j][0],py[j][0],pz[j][0])
                                      ,Point(px[j][1],py[j][1],pz[j][1]));
        // else d[j][i]=d[i][j]=calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],px[j][0],py[j][0],pz[j][0],px[j][1],py[j][1],pz[j][1]);
      }
    }
    for(int k=0;k<N;k++)
      for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
          d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    int spos=-1,gpos=-1;
    for(int i=0;i<N;i++){
      if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],sx,sy,sz)))spos=i;
      if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],gx,gy,gz)))gpos=i;
    }
    printf("%.10f\n",d[spos][gpos]);
  }
  
  
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1336
final_rank: 3

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#define REP(i,n) for(int i=0;i<(int)n;++i)
#ifdef __GNUC__
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T val){
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  val = (val + (val >> 4)) & 0x0f0f0f0f;
  val += val >> 8;
  val += val >> 16;
  return (int)(val & 0x0000003f);
}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> void PrintSeq(T &a,int sz){for(int i=0;i<sz;i++){cout<<a[i];if(sz==i+1)cout<<endl;else cout<<' ';}}
ll getTen(int a){return (a<=0)?1:(getTen(a-1)*10);}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}

int N;
double sy,sx,sz;
double gy,gx,gz;
double px[101][2];
double py[101][2];
double pz[101][2];
double d[101][101];

// 線分と点の間の距離を計算(3次元)
double calcDist(double x0,double y0,double z0,double x1,double y1,double z1,double px,double py,double pz){
  double res=0;
  double dy=y1-y0;
  double dz=z1-z0;
  double dx=x1-x0;
  double a=dx*dx+dy*dy+dz*dz;
  double b=dx*x0+dy*y0+dz*z0;
  double c=(dx*px+dy*py+dz*pz);
  double t=0;
  if(!EQ(a,0))t=(c-b)/a;
  double ox=x0+dx*t;
  double oy=y0+dy*t;
  double oz=z0+dz*t;
  res=sqrt((ox-px)*(ox-px)+(oy-py)*(oy-py)+(oz-pz)*(oz-pz));
  return res;
}


double calcDist(double x0,double y0,double z0,double x1,double y1,double z1
                ,double x2,double y2,double z2,double x3,double y3,double z3){
  double res=0;
  double a1=(x3-x2)*(x1-x0)+(y3-y2)*(y1-y0)+(z3-z2)*(z1-z0);
  double a2=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)+(z1-z0)*(z1-z0);
  double a3=(x1-x0)*(x2-x0)+(y1-y0)*(y2-y0)+(z1-z0)*(z2-z0);
  double b1=(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)+(z3-z2)*(z3-z2);
  double b2=(x1-x0)*(x3-x2)+(y1-y0)*(y3-y2)+(z1-z0)*(z3-z2);
  double b3=(x3-x2)*(x2-x0)+(y3-y2)*(y2-y0)+(z3-z2)*(z2-z0);
  double t,s;
  // cout<<a1<<" "<<a2<<" "<<a3<<" ";
  // cout<<b1<<" "<<b2<<" "<<b3<<endl;
  if(a1==0){
    t=a3/a2;
    s=(t*b2-b3)/b1;
  }
  else if(a2==0){
    s=-a3/a1;
    t=(s*b1+b3)/b2;
  }
  else if(b1==0){
    t=b3/b2;
    s=(t*a2-a3)/a1;
  }
  else if(b2==0){
    s=-b3/b1;
    t=(s*a1+a3)/a2;
  }
  else{
    if(a2*b1-a1*b2==0)t=0;
    else t=(a3*b1-a1*b3)/(a2*b1-a1*b2);
    s=(t*a2-a3)/a1;
  }
  
  double p1x=x0+t*(x1-x0);
  double p1y=y0+t*(y1-y0);
  double p1z=z0+t*(z1-z0);

  double p2x=x2+s*(x3-x2);
  double p2y=y2+s*(y3-y2);
  double p2z=z2+s*(z3-z2);

  res=sqrt((p1x-p2x)*(p1x-p2x)+(p1y-p2y)*(p1y-p2y)+(p1z-p2z)*(p1z-p2z));
  
  return res;
}

struct Point{
  double x,y,z;
  Point(double x_,double y_,double z_){
    x=x_;
    y=y_;
    z=z_;
  }
  Point(){}
};

Point cross(Point p1,Point p2){
  return Point(p1.y*p2.z-p1.z*p2.y,p1.z*p2.x-p1.x*p2.z,p1.x*p2.y-p1.y*p2.x);
}
double dot(Point p1,Point p2){
  return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
double abs(Point p){
  return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}

/*
  線分間距離ではなく、直線間距離を計算
 */

int main(){

  while(cin>>N&&N){
    cin>>sx>>sy>>sz>>gx>>gy>>gz;
    for(int i=0;i<N;i++)
      for(int j=0;j<2;j++)
        cin>>px[i][j]>>py[i][j]>>pz[i][j];
    // すべての線分間の距離を計算
    for(int i=0;i<N;i++){
      for(int j=i;j<N;j++){
        if(i==j)d[i][j]=0;
        else{
          d[j][i]=d[i][j]=calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1]
                           ,px[j][0],py[j][0],pz[j][0],px[j][1],py[j][1],pz[j][1]);
        }
      }
    }
    for(int k=0;k<N;k++)
      for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
          d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    //double res=1e+15;
    // // sy,sx,szとgx,gy,gzの２点がどのノード上に乗っているか調べる
    // for(int i=0;i<N;i++){
    //   for(int j=0;j<N;j++){
    //     double dist=calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],sx,sy,sz);
    //     //cout<<i<<" "<<j<<" "<<dist<<endl;
    //     dist+=calcDist(px[j][0],py[j][0],pz[j][0],px[j][1],py[j][1],pz[j][1],gx,gy,gz);
    //     dist+=d[i][j];
    //     res=min(res,dist);
    //   }
    // }
    //printf("%.10f\n",res);
    int spos=-1,gpos=-1;
    for(int i=0;i<N;i++){
      if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],sx,sy,sz)))spos=i;
      if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],gx,gy,gz)))gpos=i;
    }
    //cout<<spos<<" "<<gpos<<endl;
    printf("%.10f\n",d[spos][gpos]);
  }
  
  
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1336
final_rank: 3

code_snippet: #include<cmath>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-8;

struct point3{
	double x,y,z;
	point3():x(0),y(0),z(0){}
	point3(double x,double y,double z):x(x),y(y),z(z){}
	point3 operator+(const point3 &a)const{ return point3(x+a.x,y+a.y,z+a.z); }
	point3 operator-(const point3 &a)const{ return point3(x-a.x,y-a.y,z-a.z); }
};

point3 operator*(double c,const point3 &a){ return point3(c*a.x,c*a.y,c*a.z); }

struct line3{
	point3 a,b;
	line3(){}
	line3(const point3 &a,const point3 &b):a(a),b(b){}
};

double abs(const point3 &a){ return sqrt(a.x*a.x+a.y*a.y+a.z*a.z); }

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

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

double dist(const line3 &L,const point3 &p){
	return abs(cross(L.b-L.a,p-L.a))/abs(L.a-L.b);
}

double dist(const line3 &L,const line3 &M){
	point3 u=L.b-L.a,v=M.b-M.a,w=L.a-M.a;
	if(abs(cross(u,v))<EPS){
		return dist(L,M.a);
	}
	else{
		// a*s+b*t=e
		// c*s+d*t=f
		double a= dot(u,u),b=-dot(u,v),c=-dot(u,v);
		double d= dot(v,v),e=-dot(u,w),f= dot(v,w);
		double det=a*d-b*c;
		double s=( d*e-b*f)/det;
		double t=(-c*e+a*f)/det;
		return abs((L.a+s*u)-(M.a+t*v));
	}
}

int main(){
	for(int n;scanf("%d",&n),n;){
		point3 s,g;
		scanf("%lf%lf%lf%lf%lf%lf",&s.x,&s.y,&s.z,&g.x,&g.y,&g.z);
		line3 L[100];
		rep(i,n) scanf("%lf%lf%lf%lf%lf%lf",&L[i].a.x,&L[i].a.y,&L[i].a.z,&L[i].b.x,&L[i].b.y,&L[i].b.z);

		static double d[102][102];
		rep(i,n){
			rep(j,i) d[i][j]=d[j][i]=dist(L[i],L[j]);
			d[i][ n ]=d[ n ][i]=dist(L[i],s);
			d[i][n+1]=d[n+1][i]=dist(L[i],g);
		}
		d[n][n+1]=d[n+1][n]=abs(s-g);

		rep(k,n+2) rep(i,n+2) rep(j,n+2) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);

		printf("%.9f\n",d[n][n+1]);
	}

	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1184
final_rank: 2