Language: C

#include <cstdio>
#include <iostream>
#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>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef pair<P,P> Edge;
typedef long long ll;

const double PI=4*atan(1.0);
const int MAX_SIZE = 10000;

// 内積
double dot(P a, P b) {
  return (a.real() * b.real() + a.imag() * b.imag());
}
// 外積
double cross(P a, P b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}
// 点cが直線ab上にあるかないか
int is_point_on_line(P a, P b, P c) {
  return EQ( cross(b-a, c-a), 0.0 );
}
// 2直線の直行判定
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ( dot(a1-a2, b1-b2), 0.0 );
}
// 2直線の平行判定
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ( cross(a1-a2, b1-b2), 0.0 );
}
// 点a,bを通る直線と点cの間の距離
double distance_l_p(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// 点a,bを端点とする線分と点cとの距離
double distance_ls_p(P a, P b, P c) {
  if ( dot(b-a, c-a) < EPS ) return abs(c-a);
  if ( dot(a-b, c-b) < EPS ) return abs(c-b);
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// 点が多角形の中に存在するかどうか
bool isInPolygon(vector<P> &points,P s){
	if(points.size()==1)return false;
	vector<P> v;
	for(int i=0;i<(int)points.size();i++)v.push_back(points[i]-s);
	int sign=0;
	for(int i=1;i<=(int)v.size();i++){
		int prv=(i-1+v.size())%v.size();
		int cur=i%v.size();
		double c=cross(v[prv],v[cur]);
		if(EQ(c,0))continue;
		else if(sign==0){
			if(c>0)sign=1;
			else sign=-1;
		}
		else{
			if(sign==-1&&c>0)return false;
			else if(sign==1&&c<0)return false;
		}
	}
	return true;
}
struct Rec{
	vector<P> p;
};
// a1,a2を端点とする線分とb1,b2を端点とする線分の交差判定
int is_intersected_ls(P a1, P a2, P b1, P b2) {
    // 線分が平行な場合は重なっていないことにする
    if(abs(cross(a2-a1,b2-b1)) < EPS){
      return 0;
    }
    return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
        ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
}
// aとbの矩形が接しているかどうか(どちらかがどちからを含んでいるものもふくむ
bool isTouchRectangle(Rec &a,Rec &b){
	// aの各頂点がbの中に存在しているかチェック
	for(int i=0;i<4;i++)if(isInPolygon(b.p,a.p[i]))return true;
	// 逆
	for(int i=0;i<4;i++)if(isInPolygon(a.p,b.p[i]))return true;
	// 各辺が他方のどれかの辺と接しているか
	for(int i=0;i<4;i++){
		int curi=i;
		int prvi=(i-1+4)%4;
		for(int j=0;j<4;j++){
			int curj=j;
			int prvj=(j-1+4)%4;
			if(is_intersected_ls(a.p[curi],a.p[prvi],b.p[curj],b.p[prvj]))return true;
		}
	}
	return false;
}
// a1,a2を端点とする線分とb1,b2を端点とする線分の交点計算
P intersection_ls(P a1, P a2, P b1, P b2) {
  P b = b2-b1;
  double d1 = abs(cross(b, a1-b1));
  double d2 = abs(cross(b, a2-b1));
  double t = d1 / (d1 + d2);

  return a1 + (a2-a1) * t;
}
// a1,a2を通る直線とb1,b2を通る直線の交差判定
int is_intersected_l(P a1, P a2, P b1, P b2) {
  return !EQ( cross(a1-a2, b1-b2), 0.0 );
}
// a1,a2を通る直線とb1,b2を通る直線の交点計算
P intersection_l(P a1, P a2, P b1, P b2) {
  P a = a2 - a1; P b = b2 - b1;
  return a1 + a * cross(b, b1-a1) / cross(b, a);
}
// 単位ベクトルを求める
P normalVector(P p){
	return p/abs(p);
}
// 法線ベクトルを求める
P unitVector(P a){
	return P(-a.imag(),a.real());
}
// 単位法線ベクトルを求める
P unitNormalVector(P tmp){
	P e=P(-tmp.imag(),tmp.real());
	e/=abs(e);
	return e;
}
// 座標の回転(座標pにある点を,半時計回りにa(ラジアン)回転)
P roundPoint(P p,double a){
	return P(cos(a)*p.real()-sin(a)*p.imag(),sin(a)*p.real()+cos(a)*p.imag());
}
/*
円周と線分の交差判定
*/
bool isCircleCrossLine(P a,P b,P c,double r){
	double d1 = abs(a-c);
	double d2 = abs(b-c);
    // 線分が中に含まれるとき、ここのコメントアウトをはずせばtrue(交差)となる
	//if(d1<r&&d2<r)
	//	return true;
	double d = distance_ls_p(a,b,c);
	return (EQ(d,r)||d<r);
}
// 三角形の内部に点があるかどうか
// 外積の正負がすべて同じなら内部に点あり
bool isInTriangle(P p1,P p2,P p3,P s){
	P a=p1-s;
	P b=p2-s;
	P c=p3-s;
	return ((cross(a,b)>0&&cross(b,c)>0&&cross(c,a)>0)||(cross(a,b)<0&&cross(b,c)<0&&cross(c,a)<0));
}
// 矩形の中に点が存在するかどうか
bool isInRectangle(P p1,P p2,P p3,P p4,P s){
	P a=p1-s;
	P b=p2-s;
	P c=p3-s;
    P d=p4-s;
	return ((cross(a,b)>0&&cross(b,c)>0&&cross(c,d)>0&&cross(d,a)>0)
        ||(cross(a,b)<0&&cross(b,c)<0&&cross(c,d)<0&&cross(d,a)<0));
}
// 三角形の面積を座標から計算
double calcAreaOfTriangle(P a,P b,P c){
	return abs((b.real()-a.real())*(c.imag()-a.imag()) - (c.real()-a.real())*(b.imag()-a.imag()))/2;
}
// 与えられた円の範囲内に点が存在するかどうか
bool isContainingDot(P c,double r,P a){
	return (((c.real()-a.real())*(c.real()-a.real())
		+(c.imag()-a.imag())*(c.imag()-a.imag())<r*r)
		||EQ((c.real()-a.real())*(c.real()-a.real())
		+(c.imag()-a.imag())*(c.imag()-a.imag()),r*r));
}
// 多角形の面積公式
double calcPolygonArea(vector<P> p){
	double sum=0;
	for(int i = 0; i < p.size(); i++)
		sum+=cross(p[i],p[(i+1)%(p.size())]);
	return abs(sum/2);
}
// 2ベクトル間の角度
// aからbへ左周りで何度か(0->2*PI)
double diffAngle(P a,P b){
    double angle=atan2(cross(a,b),dot(a,b));
    if(angle<0)
        return 2*PI+angle;
    return angle;
}
// 2つのベクトルの重なっている部分の長さを返す
// もし重なっていなければ0を返す
double multipleLength(P a,P b,P c,P d){
    Edge e1=make_pair(a,b);
    Edge e2=make_pair(c,d);
    // 平行であるかどうか
    if(!(is_parallel(e1.first,e2.first,e1.second,e2.second)
        &&is_parallel(e1.first,e1.second,e2.first,e2.second)))
        return 0;
    double dist=0;
    // 両方乗っている
    if(EQ(distance_ls_p(e1.first,e1.second,e2.first),0)&&EQ(distance_ls_p(e1.first,e1.second,e2.second),0))
        dist=abs(e2.first-e2.second);
    else if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0)&&EQ(distance_ls_p(e2.first,e2.second,e1.second),0))
        dist=abs(e1.first-e1.second);
    else if(EQ(distance_ls_p(e1.first,e1.second,e2.first),0)){
        // どちらが線上にあるか
        if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0))
            dist=abs(e1.first-e2.first);
        else
            dist=abs(e1.second-e2.first);
    }
    else if(EQ(distance_ls_p(e1.first,e1.second,e2.second),0)){
        if(EQ(distance_ls_p(e2.first,e2.second,e1.first),0))
            dist=abs(e1.first-e2.second);
        else
            dist=abs(e1.second-e2.second);
    }
    return dist;
}
// 2点を通る半径rの円の中点を求める
pair<P,P> calcCircleCenterPoint(P dot1,P dot2,double r){
    double v=abs(dot1-dot2);
    double x = sqrt(r*r - (v/2)*(v/2));
    // 二組の単位法線ベクトル
    P hose[2];
    double x1=-(dot1.imag()-dot2.imag());
    double y1=(dot1.real() - dot2.real());
    hose[0]=P(x1,y1);
    double y2=-y1;
    double x2=-x1;
    hose[1]=P(x2,y2);
    double dd1=abs(hose[0]);
    double dd2=abs(hose[1]);
    hose[0]/=dd1;hose[0]*=x;
    hose[1]/=dd2;hose[1]*=x;
    P tmp=(dot1+dot2);
    tmp/=2;
    hose[0]+=tmp;
    hose[1]+=tmp;
    return make_pair(hose[0],hose[1]);
}
// 4線分が端点以外でクロスしているかどうかを判定
bool checkCross(const vector<Edge> &vec){
    for(int i=0;i<vec.size();i++){
        for(int j=i+1;j<vec.size();j++){
            // 線分がクロスしているかどうか
            if(is_intersected_ls(vec[i].first,vec[i].second,vec[j].first,vec[j].second)){
                // している場合、端点以外でクロスしているなら、false
                P p=intersection_ls(vec[i].first,vec[i].second,vec[j].first,vec[j].second);
                if(!(EQ(p,vec[i].first)||EQ(p,vec[i].second)))
                    return false;
            }
        }
    }
    return true;
}
// 引き数で与えられた4つの点が矩形を作るどうかを判定
bool checkRec(const vector<P> &squ){
    vector<int> v;
    for(int i=0;i<squ.size();i++)v.push_back(i);
    do{
        vector<Edge> ve;
        for(int i=0;i<4;i++)
            ve.push_back(make_pair(squ[v[i]],squ[v[(i+1)%4]]));
        // ここですべての線分がクロスするかどうかを計算
        if(checkCross(ve)){
            // 線分の長さを確認
            if(EQ(abs(ve[0].first-ve[0].second),abs(ve[2].first-ve[2].second)))
                if(EQ(abs(ve[1].first-ve[1].second),abs(ve[3].first-ve[3].second)))
                    // 直行
                    if(is_orthogonal(ve[0].first,ve[0].second,ve[1].first,ve[1].second))
                        if(is_orthogonal(ve[2].first,ve[2].second,ve[3].first,ve[3].second))
                        return true;
        }
    }while(next_permutation(v.begin(),v.end()));
    return false;
}
// 引き数で与えられた4つの点が正方形を作るかどうかを判定
bool checkSqu(const vector<P> &squ){
    vector<int> v;
    for(int i=0;i<squ.size();i++)v.push_back(i);
    do{
        vector<Edge> ve;
        for(int i=0;i<4;i++)
            ve.push_back(make_pair(squ[v[i]],squ[v[(i+1)%4]]));
        // ここですべての線分がクロスするかどうかを計算
        if(checkCross(ve)){
            // 線分の長さを確認
            double d=abs(ve[0].first-ve[0].second);
            for(int i=1;i<4;i++){
                double d2=abs(ve[i].first-ve[i].second);
                if(!EQ(d,d2))return false;
            }
            // 直行確認
            if(is_orthogonal(ve[0].first,ve[0].second,ve[1].first,ve[1].second))
                if(is_orthogonal(ve[2].first,ve[2].second,ve[3].first,ve[3].second))
                    return true;
        }
    }while(next_permutation(v.begin(),v.end()));
    return false;
}
// 二円の共通接線を構成する4直線を求める(二円はお互い接したりどちらかをふくんだりしない)
vector<pair<P,P> > calcCommonTangentialLine(P p1,double r1,P p2,double r2){
	vector<pair<P,P> > res;
	if(r1>r2){
		swap(r1,r2);
		swap(p1,p2);
	}
	// 共通外接線
	{
		double d=abs(p1-p2);
		double a=abs(r1-r2);
		double b=sqrt(d*d-a*a);
		double sita=acos(b/d);
		P e=normalVector(roundPoint((roundPoint((p2-p1),sita)),PI/2));
		res.push_back(make_pair(e*r1+p1,e*r2+p2));
		P e2=normalVector(roundPoint((roundPoint((p2-p1),-sita)),-PI/2));
		res.push_back(make_pair(e2*r1+p1,e2*r2+p2));
	}
	// 共通内接線
	{
		P cp=(r1*p1+r2*p2)/(r1+r2);
		double u=abs(cp-p1);
		double sita=acos(r1/u);
		P e=normalVector(roundPoint(cp-p1,sita));
		res.push_back(make_pair(e*r1+p1,-e*r2+p2));
		P e2=normalVector(roundPoint(cp-p1,-sita));
		res.push_back(make_pair(e2*r1+p1,-e2*r2+p2));
	}
	return res;
}
/*
  与えられた3点a,b,c,をa->b->cと進むとき
  a->bで時計方向に折れて,b->c
  a->bで半時計方向に折れて,b->c
  a->bで逆を向いてaを通り越してb->c
  a->bでそのままb->c
  a->bで逆を向いてb->c
  のどれであるかを判定
*/
int ccw(P a,P b, P c){
  b-=a;c-=a;
  if(cross(b,c)>0&&!EQ(cross(b,c),0))return 1;// counter clockwise
  if(cross(b,c)<0&&!EQ(cross(b,c),0))return -1;// clockwise
  if(dot(b,c)<0&&!EQ(dot(b,c),0))return 2; // c-a-b on line
  if(!EQ(abs(b),abs(c))&&abs(b)<abs(c))return -2; // a-b-c on line
  return 0;
}
// 凸多角形の切断を行う
// lineのfirst側から見て右の多角形が返る
// 多角形は上が+y,右が+xの座標系で座標を時計周りに格納したvectorで表す
// lineは基本的にmakeDivisorで作成
vector<P> convex_cut(vector<P> polygon,pair<P,P> line){
  vector<P> resPolygon;
  int n=polygon.size();
  for(int i=0;i<n;i++){
    P A=polygon[i];
    P B=polygon[(i+1)%n];
    if(ccw(line.first,line.second,A)!=-1)
      resPolygon.push_back(A);
    if(ccw(line.first,line.second,A)*ccw(line.first,line.second,B)<0)
      resPolygon.push_back(intersection_l(A,B,line.first,line.second));
  }
  return resPolygon;
}

struct Point{
  P p;
  Point(P _p){
    p=_p;
  }
  Point(){}
  bool operator<(const Point &op)const{
    if(EQ(p.real(),op.p.real())){
      if(EQ(p.imag(),op.p.imag()))return false;
      else
	return p.imag()<op.p.imag();
    }
    return p.real()<op.p.real();
  }
};
struct edge{
  double dist;
  Point to;
};

const int MAX_N=1000001;
const int INF=1000000000;
vector<edge> G[MAX_N];
double d[MAX_N];
vector<P> ps;
set<Point> nodes;
map<Point,int> m;
int idx;
int n;

typedef pair<double,int> pii;

double dijkstra(){
  for(int i=0;i<idx;i++)d[i]=INF;
  priority_queue<pii> pq;
  pq.push(pii(0,m[Point(ps[0])]));
  // start
  d[m[Point(ps[0])]]=0;
  while(pq.size()){
    pii p=pq.top();pq.pop();
    double cost=p.first;
    int node=p.second;
    if(!EQ(d[node],cost)&&d[node]<cost)continue;
    for(int i=0;i<G[node].size();i++){
      edge &e=G[node][i];
      if(d[m[e.to]]>cost+e.dist){
	d[m[e.to]]=cost+e.dist;
	pq.push(pii(d[m[e.to]],m[e.to]));
      }
    }
  }
  // ゴールへの最短距離
  return d[m[Point(ps[n-1])]];
}

int main(){
  while(cin>>n&&n){
    double vw,vc;
    idx=0;ps.clear();m.clear();nodes.clear();
    cin>>vw>>vc;
    for(int i=0;i<n;i++){
      double x,y;
      cin>>x>>y;
      ps.push_back(P(x,y));
    }
    for(int i=0;i<n;i++){
      for(int j=1;j<n;j++){
	P a=ps[j-1];
	P b=ps[j];
	// 線分a--bとy=ps[i].imag()が交差するか？
	if(is_intersected_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()))){
	  P cp=intersection_ls(a,b,P(-1000000,ps[i].imag()),P(1000000,ps[i].imag()));
	  nodes.insert(Point(cp));
	  m[Point(cp)]=idx++;
	}
      }
      nodes.insert(Point(ps[i]));
      m[Point(ps[i])]=idx++;
    }
    // 交点の位置でソートしておき
    // 一つ隣の交点は通行可能
    // その他同じy座標を持つところにも通行可能
    for(set<Point>::iterator it=nodes.begin();it!=nodes.end();it++){
      // 歩いていけるところにエッジを結ぶ
      set<Point>::iterator nxt=it;nxt++;
      if(nxt!=nodes.end()){
	edge e;
	// 隣接地点へ歩いて渡る
	e.dist=abs((it->p)-(nxt->p))/vw;
	e.to=*it;
	G[m[*nxt]].push_back(e);
	e.to=*nxt;
	G[m[*it]].push_back(e);
      }
      // 同じy座標のノードを追加
      // x座標で隣接するものを使用
      for(set<Point>::iterator iit=it;iit!=nodes.end();iit++){
	// 最初は一つ進めておく
	if(iit==it)iit++;
	if(iit==nodes.end())break;
	if(EQ(iit->p.imag(),it->p.imag())){
	  set<Point>::iterator itnxt=it;itnxt++;
	  // 隣は歩いていけるのでx
	  if(itnxt!=iit){
	    edge e;
	    e.dist=abs((iit->p)-(it->p))/vc;
	    e.to=*iit;
	    G[m[*it]].push_back(e);
	  }
	  break;
	}
      }
      for(set<Point>::iterator iit=it;;iit--){
	if(iit==nodes.begin())break;
	// 最初は一つ進めておく
	if(iit==it)iit--;
	// y座標が一致
	if(EQ(iit->p.imag(),it->p.imag())){
	  set<Point>::iterator itnxt=it;itnxt--;
	  // 隣は歩いていけるのでx
	  if(itnxt!=iit){
	    edge e;
	    e.dist=abs((iit->p)-(it->p))/vc;
	    e.to=*iit;
	    G[m[*it]].push_back(e);
	  }
	  break;
	}
	if(iit==nodes.begin())break;
      }
    }
    double res=dijkstra();
    printf("%.10f\n",res);
    for(int i=0;i<idx;i++)G[i].clear();
  }

  return 0;
}

Compiler output:
main.c:1:10: fatal error: cstdio: No such file or directory
    1 | #include <cstdio>
      |          ^~~~~~~~
compilation terminated.