#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct //構造体の定義
{
  int s_name;  //駅名
  double lati, longi;  //緯度 経度
  int s_n; //接続している駅の数
  int s_neigh[5];  //接続している駅名
  int visit;  //探索済みであるかどうかを格納する値
  int ps_name;  //探索した親の駅名
}station;



double compute_edge_weight(station st[], int v, int w){//隣接する駅同士の距離を平方根で求める
    return sqrt((st[v].lati - st[w].lati) * (st[v].lati - st[w].lati) + 
    (st[v].longi - st[w].longi) * (st[v].longi - st[w].longi));
}

void add(int s[], int u){//最短距離が確定した駅を格納する関数
  s[u] = 1;
}

select_min(double d[], int s[]){//暫定距離が最小の要素を選ぶ関数
  int min = 999,i,u;
  for (i=0; i < 6; i++) {
    if (s[i] == 0 && d[i] < min){
      min = d[i];
      u = i;
    }
  }
  return u;
} 


void search_path(station st[], double d[], int s[], int v){  //再帰的に経路を探索する関数 駅の構造体、探索したかどうかを記憶する配列、スタート地点の駅IDを引数にとる
  int w, u, i,l;
  double j, k;
  st[v].visit = 1; //探索済みなので1を代入
  if(st[v].s_name == 5) return;  //ゴールに到達すれば関数を抜ける
  for(w = 0; w < st[v].s_n; w++){ //隣接する駅の数だけループ
    d[st[v].s_neigh[w]] = d[v] + compute_edge_weight(st, v, st[v].s_neigh[w]);  //原点から現在の駅間での距離プラス現在の駅から隣接する駅までの距離の値を配列に代入
   
  }
  for(w = 0; w < st[v].s_n; w++){//隣接する駅の数だけループ
    if(s[st[v].s_neigh[w]] != 1){//隣接する駅が最短距離だと確定していなければ
      u = select_min(d, s);//隣接する駅から最小の距離のものを探し出し
      add(s, u);//それを最短距離が確定した駅に格納
      //st[u].ps_name = st[v].s_name;  //隣接する駅の親IDにこの駅のIDを入れる
      for(i = 0; i < st[u].s_n; i++){//最短距離の確定した駅から隣接する駅の数だけループ
        if(d[u] != 999 && s[st[u].s_neigh[i]] == 0){//暫定的な最短距離が入力されていて,かつ最短距離が確定していなければ
          k = compute_edge_weight(st, u, st[u].s_neigh[i]);
          if((j = d[u] + k) < d[st[u].s_neigh[i]]){//駅番号uの駅を経由して駅に行ったときの距離が暫定的な最短距離よりも短ければ
            d[st[u].s_neigh[i]] = j;//その距離を新たに代入
            //st[st[u].s_neigh[i]].ps_name = st[u].s_name;  
          }
        }
      }
    }
  }
  for(w = 0; w < st[v].s_n; w++){  //隣接する駅の数だけループ
    if(st[st[v].s_neigh[w]].visit != 1 && st[v].s_neigh[w] != u){  //隣接する駅のIDがすでに探索済みで無ければ
      search_path(st, d, s, st[v].s_neigh[w]);  //未探索の隣接する駅のIDを引数にし再帰的定義
    }
 }
}

void display_path(station st[], int v){  //発見した経路を表示する関数 ゴールの駅IDを引数にとる
  if(st[v].s_name  != 0)  //駅IDがスタート地点でなければ
    display_path(st, st[v].ps_name);  //親の駅のIDで再帰的に定義
  printf("駅ID:%d, 駅名:%s\n", st[v].s_name, st[v].s_name);  //スタックの一番上の値から順に表示
}

int main(void){
  int i;
  double d[6];//0駅からある駅までの最少距離を入れる配列
  int s[6];//最小距離が確定した駅の番号を入れる配列
  station st[6];

  st[0].s_name = 0;
  st[0].lati = 0;
  st[0].longi = 0;
  st[0].s_n = 3;
  st[0].s_neigh[0] = 1;
  st[0].s_neigh[1] = 2;
  st[0].s_neigh[2] = 3;
  
  st[1].s_name = 1;
  st[1].lati = 3;
  st[1].longi = 5;
  st[1].s_n = 2;
  st[1].s_neigh[0] = 0;
  st[1].s_neigh[1] = 5;

  
  st[2].s_name = 2;
  st[2].lati = 4;
  st[2].longi = 0;
  st[2].s_n = 4;
  st[2].s_neigh[0] = 0;
  st[2].s_neigh[1] = 1;
  st[2].s_neigh[2] = 3;
  st[2].s_neigh[3] = 4;

  
  st[3].s_name = 3;
  st[3].lati = 2;
  st[3].longi = 3;
  st[3].s_n = 3;
  st[3].s_neigh[0] = 0;
  st[3].s_neigh[1] = 2;
  st[3].s_neigh[2] = 4;

  
  st[4].s_name = 4;
  st[4].lati = 6;
  st[4].longi = 4;
  st[4].s_n = 3;
  st[4].s_neigh[0] = 2;
  st[4].s_neigh[1] = 3;
  st[4].s_neigh[2] = 5;

  
  st[5].s_name = 5;
  st[5].lati = 9;
  st[5].longi = 2;
  st[5].s_n = 2;
  st[5].s_neigh[0] = 1;
  st[5].s_neigh[1] = 4;

  for(i = 0; i < 6; i++){//最少距離に無限大を入れて初期化
    d[i] = 999;
  }
  s[0] = 1;//原点の0駅初期化
  d[0] = 0;
  search_path(st, d, s, 0);
  //display_path(st, 5);
  printf("%f", d[5]);
   return 0;
}