# poj - 2502 dijkstra 或 spfa 单位换算 建图

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define inf 0x3f3f3f3f

using namespace std;

const int maxn = 1005;
const int maxm = 100500;

int n = maxn, m, s, t;   //n为点数 s为源点
double d[maxn]; //储存到源节点的距离，在init()中初始化
bool vis[maxn]; //是否访问过
int pre[maxn];

struct node {
int num;
double dis;
node (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node a, node b) {
return a.dis > b.dis;
}
};
struct node1 {
int num;
int dis;
node1 (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node1 a, node1 b) {
if(a.dis == b.dis) return a.num < b.num;
return a.dis < b.dis;
}
};

struct edge {
int v, next;
double w;
}es[maxm];

void init() {
for(int i = 0; i < maxn; i++) {
d[i] = inf;
vis[i] = false;
pre[i] = -1;
}
nodep = 0;
}

void addedge(int from, int to, double weight)
{
es[nodep].v = to;
es[nodep].w = weight;
}

void dijkstra()
{
priority_queue<node> pq;
d[s] = 0;    //s为源点
pq.push(node(s, 0));
while(!pq.empty()) {
node num = pq.top();
pq.pop();
int u = num.num;
if(vis[u]) continue;
vis[u] = 1;
//遍历邻接表
for(int i = head[u]; i != -1; i = es[i].next) {  //在es中，相同from出发指向的顶点为从head[from]开始的一项，逐项使用next寻找下去，直到找到第一个被输
//入的项，其next值为-1
int v = es[i].v;
if(!vis[v] && d[v] > d[u] + es[i].w) { //松弛(RELAX)操作
d[v] = d[u] + es[i].w;
//pre[v] = u;
pq.push(node(v, d[v]));
}
}
}
}

void putpath() {
stack<int> path;
int now = t;
while(1) {
path.push(now);
if(now == s) {
break;
}
now = pre[now];
}
while(!path.empty()) {
now = path.top();
path.pop();
printf("%d\n", now);
}
}

int p[maxn], x[maxn], y[maxn];

double cal(int a,int b){
return sqrt(1.0 * (x[a] - x[b]) * (x[a] - x[b]) + 1.0 * (y[a] - y[b]) * (y[a] - y[b]));
}

int v[maxn][maxn] = {0};

int main()
{
init();
int T, kcase = 0;
int cnt = 0;
cin >> x[1] >> y[1] >> x[2] >> y[2];
map<node1, int> mp;
mp[node1(x[1], y[1])] = ++cnt;
mp[node1(x[2], y[2])] = ++cnt;
int x1, y1;
int c = 0;
while(scanf("%d %d", &x1, &y1) != EOF) {
if(x1 == -1 && y1 == -1) {
for(int i = 2; i <= c; i++) {
int j = i - 1;
addedge(p[i], p[j], cal(p[i], p[j]) / 40.0 * 3.6);
addedge(p[j], p[i], cal(p[i], p[j]) / 40.0 * 3.6);
v[p[i]][p[j]] = v[p[j]][p[i]] = 1;
}
c = 0;
}
else {
node1 tmp(x1, y1);
if(mp[tmp]) p[++c] = mp[tmp];
else {
p[++c] = mp[tmp] = ++cnt;
x[cnt] = x1;
y[cnt] = y1;
}
}
}
for(int i = 1; i <= cnt; i++) {
for(int j = i + 1; j <= cnt; j++) {
if(!v[i][j]) {
addedge(i, j, cal(i, j) / 10.0 * 3.6);
addedge(j, i, cal(i, j) / 10.0 * 3.6);

}
}
}
s = 1, n = cnt;
dijkstra();
printf("%d\n",(int)(d[2] / 60.0 + 0.5));
return 0;
}



#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define inf 0x3f3f3f3f

using namespace std;

const int maxn = 1005;
const int maxm = 100500;

int n, m, s, t;   //n为点数 s为源点
double d[maxn]; //储存到源节点的距离，在Spfa()中初始化
int cnt[maxn];
bool inq[maxn]; //这里inq作inqueue解释会更好，出于习惯使用了inq来命名，在Spfa()中初始化
int pre[maxn];

struct node1 {
int num;
int dis;
node1 (int a = 0, int b = 0) : num(a), dis(b) {}
friend bool operator <(node1 a, node1 b) {
if(a.dis == b.dis) return a.num < b.num;
return a.dis < b.dis;
}
};

struct node {
int v, next;
double w;
}es[maxm];

void init() {
for(int i = 1; i < maxn; i++) {
d[i] = inf;
inq[i] = false;
cnt[i] = 0;
pre[i] = -1;
}
nodep = 0;
}

void addedge(int from, int to, double weight)
{
es[nodep].v = to;
es[nodep].w = weight;
}

bool spfa()
{
queue<int> que;
d[s] = 0;    //s为源点
inq[s] = 1;
que.push(s);
while(!que.empty()) {
int u = que.front();
que.pop();
inq[u] = false;   //从queue中退出
//遍历邻接表
for(int i = head[u]; i != -1; i = es[i].next) {  //在es中，相同from出发指向的顶点为从head[from]开始的一项，逐项使用next寻找下去，直到找到第一个被输
//入的项，其next值为-1
int v = es[i].v;
if(d[v] > d[u] + es[i].w) { //松弛(RELAX)操作
d[v] = d[u] + es[i].w;
//pre[v] = u;
if(!inq[v]) {      //若被搜索到的节点不在队列que中，则把to加入到队列中去
inq[v] = true;
que.push(v);
if(++cnt[v] > n) {
return false;
}
}
}
}
}
return true;
}

void putpath() {
stack<int> path;
int now = t;
while(1) {
path.push(now);
if(now == s) {
break;
}
now = pre[now];
}
while(!path.empty()) {
now = path.top();
path.pop();
printf("%d\n", now);
}
}
int p[maxn], x[maxn], y[maxn];

double cal(int a, int b) {
return sqrt(1.0 * (x[a] - x[b]) * (x[a] - x[b]) + 1.0 * (y[a] - y[b]) * (y[a] - y[b]));
}

int v[maxn][maxn] = {0};

int main()
{
init();
int T, kcase = 0;
int cnt = 0;
cin >> x[1] >> y[1] >> x[2] >> y[2];
map<node1, int> mp;
mp[node1(x[1], y[1])] = ++cnt;
mp[node1(x[2], y[2])] = ++cnt;
int x1, y1;
int c = 0;
while(scanf("%d %d", &x1, &y1) != EOF) {
if(x1 == -1 && y1 == -1) {
for(int i = 2; i <= c; i++) {
int j = i - 1;
addedge(p[i], p[j], cal(p[i], p[j]) / 40.0 * 3.6);
addedge(p[j], p[i], cal(p[i], p[j]) / 40.0 * 3.6);
v[p[i]][p[j]] = v[p[j]][p[i]] = 1;
}
c = 0;
}
else {
node1 tmp(x1, y1);
if(mp[tmp]) p[++c] = mp[tmp];
else {
p[++c] = mp[tmp] = ++cnt;
x[cnt] = x1;
y[cnt] = y1;
}
}
}
for(int i = 1; i <= cnt; i++) {
for(int j = i + 1; j <= cnt; j++) {
if(!v[i][j]) {
addedge(i, j, cal(i, j) / 10.0 * 3.6);
addedge(j, i, cal(i, j) / 10.0 * 3.6);

}
}
}
s = 1, n = cnt;
if(spfa());
printf("%d\n", (int)(d[2] / 60.0 + 0.5));
}