Problem:
Problem B:
Turn Left
Taro got a driver’s license with a great effort in his campus days, but unfortunately there had
been no opportunities for him to drive. He ended up obtaining a gold license.
One day, he and his friends made a plan to go on a trip to Kyoto with you. At the end of their
meeting, they agreed to go around by car, but there was a big problem; none of his friends was
able to drive a car. Thus he had no choice but to become the driver.
The day of our departure has come. He is going to drive but would never turn to the right for
fear of crossing an opposite lane (note that cars keep left in Japan). Furthermore, he cannot
U-turn for the lack of his technique. The car is equipped with a car navigation system, but the
system cannot search for a route without right turns. So he asked to you: “I hate right turns,
so, could you write a program to find the shortest left-turn-only route to the destination, using
the road map taken from this navigation system?”
Input
The input consists of multiple data sets. The first line of the input contains the number of data
sets. Each data set is described in the format below:
m n
name
1
x
1
y
1
...
name
m
x
m
y
m
p
1
q
1
...
p
n
q
n
src dst
m
is the number of intersections.
n
is the number of roads.
name
i
is the name of the
i
-th
intersection. (
x
i
,
y
i
) are the integer coordinates of the
i
-th intersection, where the positive
x
goes to the east, and the positive
y
goes to the north.
p
j
and
q
j
are the intersection names
that represent the endpoints of the
j
-th road. All roads are bidirectional and either vertical or
horizontal.
src
and
dst
are the names of the source and destination intersections, respectively.
You may assume all of the followings:
2 ≤
m
≤ 1000, 0 ≤
x
i
≤ 10000, and 0 ≤
y
i
≤ 10000;
each intersection name is a sequence of one or more alphabetical characters at most 25
  character long;
no intersections share the same coordinates;
no pair of roads have common points other than their endpoints;
no road has intersections in the middle;
no pair of intersections has more than one road;
Taro can start the car in any direction; and
the source and destination intersections are different.
Note that there may be a case that an intersection is connected to less than three roads in
the input data; the rode map may not include smaller roads which are not appropriate for the
non-local people. In such a case, you still have to consider them as intersections when you go
them through.
Output
For each data set, print how many times
at least
Taro needs to pass intersections when he drive
the route of the shortest distance without right turns. The source and destination intersections
must be considered as “passed” (thus should be counted) when Taro starts from the source or
arrives at the destination. Also note that there may be more than one shortest route possible.
Print “impossible” if there is no route to the destination without right turns.
Sample Input
2 1
KarasumaKitaoji 0 6150
KarasumaNanaj
...(truncated)

Submitted solutions:

code_snippet: #include <iostream>
#include <utility>
#include <tuple>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <numeric>
#include <queue>
#include <cmath>
#include <iomanip>
#include <array>
#include <string>
#include <stack>
#include <cassert>
#include <memory>
#include <random>
#include <fstream>
#include <cfloat>
struct Vector;
struct Coordinate {
	int x{ 0 }, y{ 0 };
	Vector operator-(const Coordinate &that) const;
	double distance(const Coordinate& that) const;
};
struct Vector {
	int dx, dy;
	int cross(const Vector& that) const;
	double length() const;
};
namespace std {
	template <class T1, class T2>
	struct hash<std::pair<T1, T2>> {
		unsigned int operator() (const pair<T1, T2>& p) const {
			unsigned int lhs = hash<T1>()(p.first), rhs = hash<T2>()(p.second);
			return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
		}
	};
}
int main() {
	while (true) {
		int m, n; std::cin >> m >> n; if (m == 0 && n == 0) break;
		std::unordered_map<std::string, Coordinate> cross;
		std::unordered_map<std::string, std::vector<std::string>> connection;
		for (auto i = 0; i < m; ++i) {
			std::string name; Coordinate coord;
			std::cin >> name >> coord.x >> coord.y;
			cross[name] = coord;
		}
		std::unordered_map<std::pair<std::string, std::string>, double> min_length;
		for (auto i = 0; i < n; ++i) {
			std::string p, q; std::cin >> p >> q;
			connection[p].push_back(q);
			connection[q].push_back(p);
			min_length[std::make_pair(p, q)] = DBL_MAX;
			min_length[std::make_pair(q, p)] = DBL_MAX;
		}
		std::string src, dst; std::cin >> src >> dst;
		std::unordered_map<std::pair<std::string, std::string>, int> min_pass;
		const auto comparator = [](const std::pair<std::pair<std::string, std::string>, double>& a, const std::pair<std::pair<std::string, std::string>, double>& b) {return a.second > b.second; };
		std::priority_queue<std::pair<std::pair<std::string, std::string>, double>, std::vector<std::pair<std::pair<std::string, std::string>, double>>, decltype(comparator)> queue(comparator);
		for (const auto& next : connection[src]) {
			const auto pair = std::make_pair(next, src);
			min_length[pair] = cross[src].distance(cross[next]);
			min_pass[pair] = 2;
			queue.emplace(pair, min_length[pair]);
		}
		while (!queue.empty()) {
			const auto top = queue.top(); queue.pop();
			if (min_length[top.first] < top.second) continue;
			const auto current_vec = cross[top.first.first] - cross[top.first.second];
			for (const auto& next : connection[top.first.first]) if (next != top.first.second) {
				const auto next_vec = cross[next] - cross[top.first.first];
				if (current_vec.cross(next_vec) >= 0) {
					const auto len = next_vec.length();
					const auto pair = std::make_pair(next, top.first.first);
					if (min_length[pair] > len + top.second + 1e-10) {
						min_length[pair] = len + top.second;
						min_pass[pair] = min_pass[top.first] + 1;
						queue.emplace(pair, len + top.second);
					}
					else if (min_length[pair] == len + top.second) {
						min_pass[pair] = std::min(min_pass[pair], min_pass[top.first] + 1);
					}
				}
			}
		}
		double len{ DBL_MAX };
		int pass{ INT_MAX };
		for (const auto& prev : connection[dst]) {
			const auto pair = std::make_pair(dst, prev);
			if (min_length[pair] == DBL_MAX) continue;
			if (len > min_length[pair]) {
				len = min_length[pair];
				pass = min_pass[pair];
			}
			else if (len == min_length[pair]) {
				pass = std::min(pass, min_pass[pair]);
			}
		}
		if (pass == INT_MAX) {
			std::cout << "impossible\n";
		}
		else {
			std::cout << pass << '\n';
		}
	}
}

Vector Coordinate::operator-(const Coordinate& that) const
{
	return Vector{ x - that.x, y - that.y };
}

double Coordinate::distance(const Coordinate& that) const
{
	return (*this - that).length();
}

int Vector::cross(const Vector& that) const
{
	return dx * that.dy - dy * that.dx;
}

double Vector::length() const
{
	return std::sqrt(dx * dx + dy * dy);
}
accuracy: 1
time_ms: 90
memory_kb: 4020
final_rank: 9

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;


enum DIR{
	North,
	East,
	South,
	West,
};

struct Info{
	char name[26];
	int x,y;
};

struct Data{
	Data(int arg_to,DIR arg_dir){
		to = arg_to;
		dir = arg_dir;
	}
	int to;
	DIR dir;
};

struct State{
	State(){
		node_id = sum_dist = num_cross_point = 0;
		dir = North;
	}
	State(int arg_node_id,int arg_sum_dist,int arg_num_cross_point,DIR arg_dir){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
		num_cross_point = arg_num_cross_point;
		dir = arg_dir;
	}
	bool operator<(const struct State &arg)const{
		return sum_dist > arg.sum_dist;
	}
	int node_id,sum_dist,num_cross_point;
	DIR dir;
};

int M,N;
int min_dist[1000][4],min_cross[1000][4];
Info info[1000];
char buf1[26],buf2[26];
vector<Data> G[1000];


int calc(int node_left,int node_right){
	return abs(info[node_left].x-info[node_right].x)+abs(info[node_left].y-info[node_right].y);
}

bool strCmp(char* base, char* comp){
	int length1,length2;
	for(length1=0;base[length1] != '\0';length1++);
	for(length2=0;comp[length2] != '\0';length2++);
	if(length1 != length2)return false;

	for(int i=0;base[i] != '\0'; i++){
		if(base[i] != comp[i])return false;
	}
	return true;
}


void func(){

	for(int i = 0; i < M; i++){
		G[i].clear();
	}

	for(int i = 0; i < M; i++){
		scanf("%s %d %d",info[i].name,&info[i].x,&info[i].y);
	}

	int left_index,right_index;
	for(int loop = 0; loop < N; loop++){
		scanf("%s %s",buf1,buf2);

		for(int i = 0; i < M; i++){
			if(strCmp(info[i].name,buf1)){
				left_index = i;
				break;
			}
		}

		for(int i = 0; i < M; i++){
			if(strCmp(info[i].name,buf2)){
				right_index = i;
				break;
			}
		}

		if(info[left_index].x == info[right_index].x){
			if(info[left_index].y > info[right_index].y){
				G[left_index].push_back(Data(right_index,South));
				G[right_index].push_back(Data(left_index,North));
			}else{
				G[left_index].push_back(Data(right_index,North));
				G[right_index].push_back(Data(left_index,South));
			}
		}else{
			if(info[left_index].x > info[right_index].x){
				G[left_index].push_back(Data(right_index,West));
				G[right_index].push_back(Data(left_index,East));
			}else{
				G[left_index].push_back(Data(right_index,East));
				G[right_index].push_back(Data(left_index,West));
			}
		}
	}

	int start,goal;
	scanf("%s %s",buf1,buf2);
	for(int i = 0; i < M; i++){
		if(strCmp(info[i].name,buf1)){
			start = i;
			break;
		}
	}

	for(int i = 0; i < M; i++){
		if(strCmp(info[i].name,buf2)){
			goal = i;
			break;
		}
	}

	for(int i = 0; i < M; i++){
		for(int k = 0; k < 4; k++){
			min_dist[i][k] = BIG_NUM;
			min_cross[i][k] = BIG_NUM;
		}
	}

	for(int i = 0; i < 4; i++){
		min_dist[start][i] = 0;
		min_cross[start][i] = 1;
	}

	priority_queue<State> Q;
	for(int i = 0; i < G[start].size(); i++){
		min_dist[G[start][i].to][G[start][i].dir] = calc(start,G[start][i].to);
		min_cross[G[start][i].to][G[start][i].dir] = 2;
		Q.push(State(G[start][i].to,min_dist[G[start][i].to][G[start][i].dir],2,G[start][i].dir));
	}

	int next_node,next_dist;
	DIR next_dir;

	while(!Q.empty()){

		if(Q.top().node_id == goal){
			Q.pop();
		}else if((Q.top().sum_dist > min_dist[Q.top().node_id][Q.top().dir]) ||
				(Q.top().sum_dist == min_dist[Q.top().node_id][Q.top().dir] && Q.top().num_cross_point > min_cross[Q.top().node_id][Q.top().dir])){
			Q.pop();
		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				if(Q.top().dir == North){
					if(G[Q.top().node_id][i].dir != North && G[Q.top().node_id][i].dir != West)continue;
				}else if(Q.top().dir == West){
					if(G[Q.top().node_id][i].dir != West && G[Q.top().node_id][i].dir != South)continue;
				}else if(Q.top().dir == South){
					if(G[Q.top().node_id][i].dir != South && G[Q.top().node_id][i].dir != East)continue;
				}else{ //Q.top().dir == East
					if(G[Q.top().node_id][i].dir != East && G[Q.top().node_id][i].dir != North)continue;
				}
				next_node= G[Q.top().node_id][i].to;
				next_dist = Q.top().sum_dist+calc(Q.top().node_id,next_node);
				next_dir = G[Q.top().node_id][i].dir;

				if(min_dist[next_node][next_dir] > next_dist){
					min_dist[next_node][next_dir] = next_dist;
					min_cross[next_node][next_dir] = Q.top().num_cross_point+1;
					Q.push(State(next_node,next_dist,Q.top().num_cross_point+1,next_dir));
				}else if(min_dist[next_node][next_dir] == next_dist && min_cross[next_node][next_dir] > Q.top().num_cross_point+1){
					min_cross[next_node][next_dir] = Q.top().num_cross_point+1;
					Q.push(State(next_node,next_dist,Q.top().num_cross_point+1,next_dir));
				}
			}
			Q.pop();
		}
	}

	int final_dist = BIG_NUM,final_cross = BIG_NUM;

	for(int i = 0; i < 4; i++){
		if(min_dist[goal][i] != BIG_NUM){
			if(final_dist > min_dist[goal][i]){
				final_dist = min_dist[goal][i];
				final_cross = min_cross[goal][i];
			}else if(final_dist == min_dist[goal][i]){
				final_cross = min(final_cross,min_cross[goal][i]);
			}
		}
	}

	if(final_dist != BIG_NUM){
		printf("%d\n",final_cross);
	}else{
		printf("impossible\n");
	}

}

int main(){

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 3308
final_rank: 13

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

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

using pint = pair<int, int>;
using tint = tuple<int, int, int>;
using vint = vector<int>;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct Point {
  int x, y;
  Point(int x = 0, int y = 0):x(x), y(y){}
  Point operator + (Point p) { return Point(x+p.x, y+p.y); }
  Point operator - (Point p) { return Point(x-p.x, y-p.y); }
  Point operator * (int k) { return Point(k*x, k*y); }
};

int abs(Point p) {
  return llabs(p.x) + llabs(p.y);
}
int dist(Point a, Point b) {
  return abs(a-b);
}
int cross(Point a, Point b) {
  return a.x*b.y - a.y*b.x;
}
bool izryt(Point a, Point b) {
  return cross(a, b) < 0;
}

struct edge {
  int to, cost;
  edge(){}
  edge(int to, int cost):to(to), cost(cost){}
};

int m, n;
vector<Point> ps;
vector<string> name;
map<string, int> id;
string s, t;
vector< vector<edge> > graph;

void init() {
  ps.clear();
  ps.resize(m);
  name.clear();
  name.resize(m);
  id.clear();
  graph.clear();
  graph.resize(m);
}

struct State {
  int cur, prev, dist, pass;
  State(){}
  State(int cur, int prev, int dist, int pass)
    :cur(cur), prev(prev), dist(dist), pass(pass){}
  bool operator < (const State& s) const {
    if(dist != s.dist) return dist > s.dist;
    if(pass != s.pass) return pass > s.pass;
    return cur > s.cur;
  }
};

int mindist[1001][1001];
int minpass[1001][1001];

int dijkstra() {
  int si = id[s], ti = id[t];
  priority_queue<State> que;
  fill(mindist[0], mindist[1001], inf);
  fill(minpass[0], minpass[1001], inf);
  for(edge e : graph[si]) {
    mindist[e.to][si] = e.cost;
    minpass[e.to][si] = 2;
    que.push(State(e.to, si, e.cost, 2));
  }
  while(!que.empty()) {
    State s = que.top(); que.pop();
    int cur = s.cur, prev = s.prev;
    if(mindist[cur][prev] < s.dist) continue;
    if(minpass[cur][prev] < s.pass) continue;
    if(cur == ti) return minpass[cur][prev];
    for(edge e : graph[cur]) {
      if(e.to == prev) continue;
      Point a = ps[cur] - ps[prev];
      Point b = ps[e.to] - ps[cur];
      if(izryt(a, b)) continue;
      if(mindist[e.to][cur] < mindist[cur][prev]+e.cost) continue;
      if(mindist[e.to][cur] == mindist[cur][prev]+e.cost &&
	 minpass[e.to][cur] <= minpass[cur][prev]+1) continue;
      mindist[e.to][cur] = mindist[cur][prev]+e.cost;
      minpass[e.to][cur] = minpass[cur][prev]+1;
      que.push(State(e.to, cur, mindist[e.to][cur], minpass[e.to][cur]));
    }
  }

  return -1;
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  while(cin >> m >> n, m || n) {
    init();
    rep(i, m) {
      cin >> name[i] >> ps[i].x >> ps[i].y;
      id[name[i]] = i;
    }
    rep(i, n) {
      string p, q;
      cin >> p >> q;
      int pi = id[p], qi = id[q];
      graph[pi].emplace_back(qi, dist(ps[pi], ps[qi]));
      graph[qi].emplace_back(pi, dist(ps[pi], ps[qi]));
    }
    cin >> s >> t;
    int ans = dijkstra();
    if(ans == -1) cout << "impossible" << endl;
    else cout << ans << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 19192
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> P;
vector<P> G[1111];
struct st{
  int prev,curr,dist,pass;
  st(){}
  st(int prev,int curr,int dist,int pass):prev(prev),curr(curr),dist(dist),pass(pass){}
  bool operator<(const st &a) const{
    return dist!=a.dist?dist>a.dist:pass>a.pass;
  }
};
struct Point{
  int x,y;
  Point(){}
  Point(int x,int y):x(x),y(y){}
  Point operator+(Point a){return Point(x+a.x,y+a.y);}
  Point operator-(Point a){return Point(x-a.x,y-a.y);}
  Point operator*(int k){return Point(x*k,y*k);}
};
typedef Point Vector;
int abs(Point a){
  return abs(a.x)+abs(a.y);
}
istream &operator>>(istream &is,Point &p){
  is>>p.x>>p.y;
  return is;
}
int cross(Point a,Point b){
  return a.x*b.y-a.y*b.x;
}
bool izryt(Vector a,Vector b){
  return (cross(a,b)<0);
}
 
int dp[1111][1111];
int dp2[1111][1111];
signed main(){
  int m,n;
  while(cin>>m>>n,m||n){
    for(int i=0;i<1111;i++) G[i].clear();
    string s[m];
    Point  p[n];
    for(int i=0;i<m;i++){
      cin>>s[i]>>p[i];
    }
    string a[n],b[n];
    for(int i=0;i<n;i++) cin>>a[i]>>b[i];
    string src,dst;
    cin>>src>>dst;
    map<string,int> ms;
    for(int i=0;i<m;i++) ms[s[i]]=i;
    for(int i=0;i<n;i++){
      G[ms[a[i]]].push_back(P(abs(p[ms[b[i]]]-p[ms[a[i]]]),ms[b[i]]));
      G[ms[b[i]]].push_back(P(abs(p[ms[b[i]]]-p[ms[a[i]]]),ms[a[i]]));
    }
    priority_queue<st> q;
    int INF=1LL<<55LL;
    for(int i=0;i<1111;i++)
      for(int j=0;j<1111;j++)
	dp[i][j]=dp2[i][j]=INF;
    for(P e:G[ms[src]]){
      //cout<<e.first<<" "<<e.second<<endl;
      dp[ms[src]][e.second]=e.first;
      dp2[ms[src]][e.second]=2;
      q.emplace(ms[src],e.second,e.first,2);
    }
    int ans=-1;
    while(!q.empty()){
      st pp=q.top();q.pop();
      int prev=pp.prev,curr=pp.curr,dist=pp.dist,pass=pp.pass;
      //cout<<prev<<" "<<curr<<" "<<dist<<" "<<pass<<endl; 
      if(dp[prev][curr]<dist) continue;
      if(dp[prev][curr]==dist&&dp2[prev][curr]<pass) continue;
      if(curr==ms[dst]){
	ans=dp2[prev][curr];
	break;
      }
      //cout<<prev<<" "<<curr<<" "<<dist<<" "<<pass<<endl; 
      Vector c,d;
      for(P e:G[curr]){
	if(e.second==prev) continue;
	c=p[curr]-p[prev];
	d=p[e.second]-p[curr];
	if(izryt(c,d)) continue;
	if(dp[curr][e.second]<dp[prev][curr]+e.first) continue;
	if(dp[curr][e.second]==dp[prev][curr]+e.first&&
	   dp2[curr][e.second]<=dp2[prev][curr]+1) continue;
	dp[curr][e.second]=dp[prev][curr]+e.first;
	dp2[curr][e.second]=dp2[prev][curr]+1;
	q.emplace(curr,e.second,dp[curr][e.second],dp2[curr][e.second]);
      }
    }
 
    if(ans<0) cout<<"impossible"<<endl;
    else cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 23212
final_rank: 20

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

int M,N;
typedef pair<int,int> P;
int X[1111],Y[1111];

const int INF = (1<<29);

//up,right,down,left;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
P G[1111][4];

void add_edge(int i,int j){
  if( X[i] != X[j] ) {
    if( X[i] > X[j] ) swap( i, j );
    G[i][1] = P(j, X[j]-X[i]);
    G[j][3] = P(i, X[j]-X[i]);
  } else {
    if( Y[i] > Y[j] ) swap( i, j );
    G[i][0] = P(j, Y[j]-Y[i]);
    G[j][2] = P(i, Y[j]-Y[i]);
  }
}

struct state{
  int id,d,ky,ps;
  state(){}
  state(int id,int d,int ky,int ps):id(id),d(d),ky(ky),ps(ps){}
  bool operator<(const state& st) const{
    if( ky == st.ky ) return ps > st.ps;
    return ky > st.ky;
  }
};

P H[1111][4];

bool isright(int d,int nd){
  if( (d+1)%4 == nd ) return true;
  return false;
}

void solve(int s,int t){
  for(int i=0;i<=M;i++)
    for(int j=0;j<4;j++)
      H[i][j] = P(INF,INF);
  priority_queue<state> q;  
  q.emplace( s, 0, 0, 1 );
  q.emplace( s, 1, 0, 1 );
  q.emplace( s, 2, 0, 1 );
  q.emplace( s, 3, 0, 1 );
  H[s][0] = P(0,1);
  H[s][1] = P(0,1);
  H[s][2] = P(0,1);
  H[s][3] = P(0,1);

  while( !q.empty() ) {
    state st = q.top(); q.pop();    
    if( H[st.id][st.d] < P(st.ky,st.ps) ) continue;
    //cout << st.id << " "<< st.d << " "<< st.ky << " " << st.ps << endl;
    if(st.id==t){
      cout << st.ps << endl;
      return;                            
    }
    for(int i=0;i<4;i++){
      if( isright( st.d, i ) ) continue;
      if( (i+2)%4 == st.d ) continue;
      P to = G[st.id][i]; if( to.second == INF ) continue;
      P nc = P( st.ky + to.second, st.ps + 1 );
      if( H[to.first][i] > nc ){
        H[to.first][i] = nc;
        q.emplace( to.first, i, nc.first, nc.second);
      }      
    }
  }
  cout << "impossible" << endl;  
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  while( cin >> M >> N && (M|N) ){
    for(int i=0;i<M;i++)
      for(int j=0;j<4;j++)
        G[i][j] = P(INF,INF);
    unordered_map<string,int> mp;
    for(int i=0;i<M;i++){
      string s; cin >> s;
      cin >> X[i] >> Y[i];
      mp[s] = i;
    }
    for(int i=0;i<N;i++){
      string a,b; cin >> a >> b;
      add_edge( mp[a], mp[b] );
    }
    /*  for(int i=0;i<M;i++){
      for(int j=0;j<4;j++){
        cout << i << ": " << j << " -> " << G[i][j].first << " "<< G[i][j].second << endl;
      }
    }
    */
    string src,dst; cin >> src >> dst;
    solve(mp[src],mp[dst]);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3312
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> P;
vector<P> G[1111];
struct st{
  int prev,curr,dist,pass;
  st(){}
  st(int prev,int curr,int dist,int pass):prev(prev),curr(curr),dist(dist),pass(pass){}
  bool operator<(const st &a) const{
    return dist!=a.dist?dist>a.dist:pass>a.pass;
  }
};
struct Point{
  int x,y;
  Point(){}
  Point(int x,int y):x(x),y(y){}
  Point operator+(Point a){return Point(x+a.x,y+a.y);}
  Point operator-(Point a){return Point(x-a.x,y-a.y);}
  Point operator*(int k){return Point(x*k,y*k);}
};
typedef Point Vector;
int abs(Point a){
  return abs(a.x)+abs(a.y);
}
istream &operator>>(istream &is,Point &p){
  is>>p.x>>p.y;
  return is;
}
int cross(Point a,Point b){
  return a.x*b.y-a.y*b.x;
}
bool izryt(Vector a,Vector b){
  return (cross(a,b)<0);
}

int dp[1111][1111];
int dp2[1111][1111];
signed main(){
  int m,n;
  while(cin>>m>>n,m||n){
    for(int i=0;i<1111;i++) G[i].clear();
    string s[m];
    Point  p[n];
    for(int i=0;i<m;i++){
      cin>>s[i]>>p[i];
    }
    string a[n],b[n];
    for(int i=0;i<n;i++) cin>>a[i]>>b[i];
    string src,dst;
    cin>>src>>dst;
    map<string,int> ms;
    for(int i=0;i<m;i++) ms[s[i]]=i;
    for(int i=0;i<n;i++){
      G[ms[a[i]]].push_back(P(abs(p[ms[b[i]]]-p[ms[a[i]]]),ms[b[i]]));
      G[ms[b[i]]].push_back(P(abs(p[ms[b[i]]]-p[ms[a[i]]]),ms[a[i]]));
    }
    priority_queue<st> q;
    int INF=1LL<<55LL;
    for(int i=0;i<1111;i++)
      for(int j=0;j<1111;j++)
	dp[i][j]=dp2[i][j]=INF;
    for(P e:G[ms[src]]){
      //cout<<e.first<<" "<<e.second<<endl;
      dp[ms[src]][e.second]=e.first;
      dp2[ms[src]][e.second]=2;
      q.emplace(ms[src],e.second,e.first,2);
    }
    int ans=-1;
    while(!q.empty()){
      st pp=q.top();q.pop();
      int prev=pp.prev,curr=pp.curr,dist=pp.dist,pass=pp.pass;
      //cout<<prev<<" "<<curr<<" "<<dist<<" "<<pass<<endl; 
      if(dp[prev][curr]<dist) continue;
      if(dp[prev][curr]==dist&&dp2[prev][curr]<pass) continue;
      if(curr==ms[dst]){
	ans=dp2[prev][curr];
	break;
      }
      //cout<<prev<<" "<<curr<<" "<<dist<<" "<<pass<<endl; 
      Vector c,d;
      for(P e:G[curr]){
	if(e.second==prev) continue;
	c=p[curr]-p[prev];
	d=p[e.second]-p[curr];
	if(izryt(c,d)) continue;
	if(dp[curr][e.second]<dp[prev][curr]+e.first) continue;
	if(dp[curr][e.second]==dp[prev][curr]+e.first&&
	   dp2[curr][e.second]<=dp2[prev][curr]+1) continue;
	dp[curr][e.second]=dp[prev][curr]+e.first;
	dp2[curr][e.second]=dp2[prev][curr]+1;
	q.emplace(curr,e.second,dp[curr][e.second],dp2[curr][e.second]);
      }
    }

    if(ans<0) cout<<"impossible"<<endl;
    else cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 23256
final_rank: 19

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define MAX 1010
#define INF 1e9
 
struct Intersection{
    int x,y;
};
 
struct State{
    int dist,v,dir,c;
    State(int dist,int v,int dir,int c) :
	dist(dist),v(v),dir(dir),c(c) {}
    bool operator < (const State &s)const{
	if(dist != s.dist){
	    return dist > s.dist;
	}else{
	    return c > s.c;
	}
    }
};
 
int M,N;
string src,dst;
vector<int> G[MAX];
Intersection n[MAX];
map<string,int> num;
 
int nextdir(int xs,int ys,int xt,int yt,int dir){
    if(dir == 0){
	if(xs < xt) return -1;
	if(ys > yt) return -1;
	if(xs > xt) return 3;
	return 0;
    }else if(dir == 1){
	if(ys > yt) return -1;
	if(xs > xt) return -1;
	if(ys < yt) return 0;
	return 1;
    }else if(dir == 2){
	if(xs > xt) return -1;
	if(ys < yt) return -1;
	if(xs < xt) return 1;
	return 2;
    }else{
	if(ys < yt) return -1;
	if(xs < xt) return -1;
	if(ys > yt) return 2;
	return 3;
    }
}
 
int getDist(int x1,int y1,int x2,int y2){
    return max(abs(x2-x1),abs(y2-y1));
}
 
void solve(){
    priority_queue<State> Q;
    int dist[MAX][4];
    fill(dist[0],dist[0]+MAX*4,INF);
    for(int i = 0 ; i < 4 ; i++){
	Q.push(State(0,num[src],i,1));
	dist[num[src]][i] = 0;
    }
    while(!Q.empty()){
	State s = Q.top(); Q.pop();
	int v = s.v,dir = s.dir;
	if(dist[v][dir] < s.dist) continue;
	if(v == num[dst]){
	    cout << s.c << endl;
	    return;
	} 
	Intersection ni = n[v];
	for(int i = 0 ; i < (int)G[v].size() ; i++){
	    Intersection u = n[G[v][i]];
	    int ndir = nextdir(ni.x,ni.y,u.x,u.y,dir);
	    if(ndir == -1) continue;
	    int ndist = s.dist + getDist(ni.x,ni.y,u.x,u.y);
	    if(ndist < dist[G[v][i]][ndir]){
		dist[G[v][i]][ndir] = ndist;
		Q.push(State(ndist,G[v][i],ndir,s.c+1));
	    }
	}
    }
    cout << "impossible" << endl;
}
 
int main(){
    string name,a,b;
    int x,y;
    while(cin >> M >> N, M){
	num.clear();
	for(int i = 0 ; i < MAX ; i++){
	    G[i].clear();
	}
	for(int i = 0 ; i < M ; i++){
	    cin >> name >> x >> y;
	    n[i+1] = (Intersection){x,y};
	    num[name] = i+1;
	}
	for(int i = 0 ; i < N ; i++){
	    cin >> a >> b;
	    G[num[a]].push_back(num[b]);
	    G[num[b]].push_back(num[a]);
	}
	cin >> src >> dst;
	solve();
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3392
final_rank: 7

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_M = 1000;
const int INF = 1 << 30;

const int dxs[] = {1, 0, -1, 0};
const int dys[] = {0, 1, 0, -1};

/* typedef */

typedef pair<int,int> pii;
typedef vector<pii> vpii;

struct ISect {
  int i, x, y;
  int nbrs[4], ds[4];
};

struct Stat {
  int d, i, di;
  Stat() {};
  Stat(int _d, int _i, int _di): d(_d), i(_i), di(_di) {};
  bool operator>(const Stat& s0) const { return d > s0.d; }
  void print() { printf("Stat:d=%d, i=%d, di=%d\n", d, i, di); }
};

/* global variables */

int m, n;
ISect isects[MAX_M];
map<string,int> nmhash;
int dists[MAX_M][4], npis[MAX_M][4];

/* subroutines */

/* main */

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

    nmhash.clear();

    for (int i = 0; i < m; i++) {
      string name;
      cin >> name >> isects[i].x >> isects[i].y;
      isects[i].i = i;
      nmhash[name] = i;
      for (int j = 0; j < 4; j++)
	isects[i].nbrs[j] = -1, isects[i].ds[j] = 0;
    }

    for (int i = 0; i < n; i++) {
      string nm0, nm1;
      cin >> nm0 >> nm1;
      ISect* is0 = &isects[nmhash[nm0]];
      ISect* is1 = &isects[nmhash[nm1]];

      int dx = is1->x - is0->x;
      int dy = is1->y - is0->y;

      if (dx != 0) {
	if (dx > 0) {
	  is0->nbrs[0] = is1->i;
	  is1->nbrs[2] = is0->i;
	  is0->ds[0] = is1->ds[2] = dx;
	}
	else {
	  is0->nbrs[2] = is1->i;
	  is1->nbrs[0] = is0->i;
	  is0->ds[2] = is1->ds[0] = -dx;
	}
      }
      else {
	if (dy > 0) {
	  is0->nbrs[1] = is1->i;
	  is1->nbrs[3] = is0->i;
	  is0->ds[1] = is1->ds[3] = dy;
	}
	else {
	  is0->nbrs[3] = is1->i;
	  is1->nbrs[1] = is0->i;
	  is0->ds[3] = is1->ds[1] = -dy;
	}
      }
    }

    string stnm, glnm;
    cin >> stnm >> glnm;

    int st = nmhash[stnm];
    int gl = nmhash[glnm];
    //printf("st=%d, gl=%d\n", st, gl);
    
    priority_queue<Stat,vector<Stat>,greater<Stat> > q;

    for (int di = 0; di < 4; di++) {
      for (int i = 0; i < m; i++) dists[i][di] = INF;
      dists[st][di] = 0;
      npis[st][di] = 1;
      q.push(Stat(0, st, di));
    }

    int min_dist = INF;
    int min_npi = 0;
    
    while (! q.empty()) {
      Stat u = q.top(); q.pop();
      //u.print();
      
      if (u.d != dists[u.i][u.di]) continue;
      if (u.i == gl) {
	if (min_dist > u.d) {
	  min_dist = u.d;
	  min_npi = npis[u.i][u.di];
	}
	else if (min_dist == u.d && min_npi > npis[u.i][u.di])
	  min_npi = npis[u.i][u.di];
	continue;
      }

      ISect& isu = isects[u.i];
      for (int di = 0; di < 2; di++) {
	int vdi = (u.di + di) & 3;
	int vi = isu.nbrs[vdi];
	if (vi >= 0) {
	  int vd = u.d + isu.ds[vdi];
	  int vnpi = npis[u.i][u.di] + 1;
	  if (dists[vi][vdi] > vd) {
	    dists[vi][vdi] = vd;
	    npis[vi][vdi] = vnpi;
	    q.push(Stat(vd, vi, vdi));
	  }
	  else if (dists[vi][vdi] == vd && npis[vi][vdi] > vnpi) {
	    npis[vi][vdi] = vnpi;
	    q.push(Stat(vd, vi, vdi));
	  }
	}
      }
    }

    if (min_dist >= INF)
      cout << "impossible" << endl;
    else
      cout << min_npi << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 1480
final_rank: 4

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

using namespace std;

#define MAX 1010
#define INF 1e9

struct Intersection{
  int x,y;
};

struct State{
  int dist,v,dir,c;
  State(int dist,int v,int dir,int c) :
    dist(dist),v(v),dir(dir),c(c) {}
  bool operator < (const State &s)const{
    if(dist != s.dist){
      return dist > s.dist;
    }else{
      return c > s.c;
    }
  }
};

int M,N;
string src,dst;
vector<int> G[MAX];
Intersection n[MAX];
map<string,int> num;

int nextdir(int xs,int ys,int xt,int yt,int dir){
  if(dir == 0){
    if(xs < xt) return -1;
    if(ys > yt) return -1;
    if(xs > xt) return 3;
    return 0;
  }else if(dir == 1){
    if(ys > yt) return -1;
    if(xs > xt) return -1;
    if(ys < yt) return 0;
    return 1;
  }else if(dir == 2){
    if(xs > xt) return -1;
    if(ys < yt) return -1;
    if(xs < xt) return 1;
    return 2;
  }else{
    if(ys < yt) return -1;
    if(xs < xt) return -1;
    if(ys > yt) return 2;
    return 3;
  }
}

int getDist(int x1,int y1,int x2,int y2){
  return max(abs(x2-x1),abs(y2-y1));
}

void solve(){
  priority_queue<State> Q;
  int dist[MAX][4];
  fill(dist[0],dist[0]+MAX*4,INF);
  for(int i = 0 ; i < 4 ; i++){
    Q.push(State(0,num[src],i,1));
    dist[num[src]][i] = 0;
  }
  while(!Q.empty()){
    State s = Q.top(); Q.pop();
    int v = s.v,dir = s.dir;
    if(dist[v][dir] < s.dist) continue;
    if(v == num[dst]){
      cout << s.c << endl;
      return;
    } 
    Intersection ni = n[v];
    for(int i = 0 ; i < (int)G[v].size() ; i++){
      Intersection u = n[G[v][i]];
      int ndir = nextdir(ni.x,ni.y,u.x,u.y,dir);
      if(ndir == -1) continue;
      int ndist = s.dist + getDist(ni.x,ni.y,u.x,u.y);
      if(ndist < dist[G[v][i]][ndir]){
        dist[G[v][i]][ndir] = ndist;
        Q.push(State(ndist,G[v][i],ndir,s.c+1));
      }
    }
  }
  cout << "impossible" << endl;
}

int main(){
  string name,a,b;
  int x,y;
  while(cin >> M >> N, M){
    num.clear();
    for(int i = 0 ; i < MAX ; i++){
      G[i].clear();
    }
    for(int i = 0 ; i < M ; i++){
      cin >> name >> x >> y;
      n[i+1] = (Intersection){x,y};
      num[name] = i+1;
    }
    for(int i = 0 ; i < N ; i++){
      cin >> a >> b;
      G[num[a]].push_back(num[b]);
      G[num[b]].push_back(num[a]);
    }
    cin >> src >> dst;
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 1512
final_rank: 5

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<cassert>
#include<cmath>
 
using namespace std;

typedef long long ll;

struct Point{
  ll x,y;
  Point operator - (const Point& p) const {
    Point res = *this;
    res.x -= p.x;
    res.y -= p.y;
    return res;
  }
};
typedef pair<ll,ll> P;

struct State{
  int now,pre;
  P t;
  bool operator < (const State& st) const {
    return t > st.t;
  }
};

ll cross(Point a, Point b){return a.x*b.y-a.y*b.x; }
 
// pre, now, next
bool isRight(Point p0, Point p1, Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  return cross(a,b) < 0;
}

const int MAX = 1050;
const ll INF = (1LL<<60);
map<string,int> idx;
vector<int> E[MAX];
Point pos[MAX];
int M,N;
P T[MAX][MAX];
 
 
void init(){
  idx.clear();
  for(int i = 0; i < MAX; i++) E[i].clear();
}
 
void input(){
 
  int cnt = 0;
  for(int i = 0; i < M; i++){
    string s;
    Point p;
    cin >> s >> p.x >> p.y;
    if(!idx.count(s)) idx[s] = cnt++;
    pos[idx[s]] = p;
  }
 
  for(int i = 0; i < N; i++){
    string p,q;
    cin >> p >> q;
    E[idx[p]].push_back(idx[q]);
    E[idx[q]].push_back(idx[p]);
  }
}

ll getDist(const Point& p1, const Point& p2){
  //return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
  return abs(p1.x-p2.x)+abs(p1.y-p2.y);
}
 
void solve(const int& src, const int& dst){
 
  fill(T[0], T[0]+MAX*MAX, P(INF,INF));
 
  priority_queue<State> Q;
  for(int i = 0; i < (int)E[src].size(); i++){
    ll d = getDist(pos[E[src][i]], pos[src]);
    T[E[src][i]][src] = P(d,2);
    Q.push((State){E[src][i],src,P(d,2)});
  }
 
  while(!Q.empty()){
    const State st = Q.top();
    Q.pop();
     
    if(T[st.now][st.pre] < st.t) continue;
 
    for(int i = 0; i < (int)E[st.now].size(); i++){
      if(st.pre == E[st.now][i]) continue;
      if(isRight(pos[st.pre], pos[st.now], pos[E[st.now][i]])) continue;
      State nex = st;
      nex.t.first += getDist(pos[st.now], pos[E[st.now][i]]);
      nex.t.second++;
      nex.now = E[st.now][i];
      nex.pre = st.now;
      if(T[nex.now][nex.pre] > nex.t){
	T[nex.now][nex.pre] = nex.t;
	Q.push(nex);
      }
    }
  }
  ll minDist = INF, res = INF;
  for(int i = 0; i < MAX; i++) minDist = min(minDist, T[dst][i].first);
  for(int i = 0; i < MAX; i++) if(T[dst][i].first == minDist) res = min(res, T[dst][i].second);
  if(res == INF) cout << "impossible" << endl;
  else cout << res << endl;
}
 
int main(){
 
  while(cin >> M >> N && M+N){
    init();
    input();
    string src, dst;
    cin >> src >> dst;
    solve(idx[src],idx[dst]);
  }
  return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 18740
final_rank: 18

code_snippet: /*
02:08 - 04:05
 */

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<unordered_map>
#include<queue>
#include<climits>

#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 MAX 2000
#define pow2(a) ((a)*(a))
#define EPS 1e-7
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

struct Point{
  double x,y;
  Point(double x=IINF,double y=IINF):x(x),y(y){}
  Point operator - (const Point& a)const { return {x-a.x,y-a.y}; }
};

struct Edge{
  int from,to;
  double dist;
  Edge(int from=IINF,int to=IINF,double dist=IINF):from(from),to(to),dist(dist){}
};

struct Data{
  int pre,cur,cost;
  double dist;
  Data(int pre=IINF,int cur=IINF,int cost=IINF,double dist=IINF):pre(pre),cur(cur),cost(cost),dist(dist){}
  bool operator < (const Data& a) const {
    if(equals(dist,a.dist))return cost > a.cost;
    return dist > a.dist;
  }
};

inline double getDist(Point a,Point b){ return sqrt(pow2(a.x-b.x)+pow2(a.y-b.y)); }
inline double cross(Point a,Point b){ return a.x*b.y-a.y*b.x; }

vector<Edge> G[MAX];
vector<Point> ps;
double mindist[MAX][MAX];//mindist[pre_node][cur_node] 
int    mincost[MAX][MAX];
int E,V,sp,gp;

void compute(){

  rep(i,V)rep(j,V){
    mindist[i][j] = IINF;
    mincost[i][j] = IINF;
  }
  priority_queue<Data> Q;
  rep(i,G[sp].size()){
    mindist[sp][G[sp][i].to] = G[sp][i].dist;
    mincost[sp][G[sp][i].to] = 2;
    Q.push(Data(sp,G[sp][i].to,2,G[sp][i].dist));
  }

  while(!Q.empty()){
    Data data = Q.top(); Q.pop();
    Point cp = ps[data.cur];
    Point pp = ps[data.pre];

    if(data.cur == gp){ cout << data.cost << endl; return; }

    rep(i,G[data.cur].size()){
      Point np = ps[G[data.cur][i].to];
      if(G[data.cur][i].to == data.pre)continue;
      if(cross(cp-pp,np-pp) < -EPS)continue;
      double dist = G[data.cur][i].dist;
      if(equals(mindist[data.cur][i],data.dist+dist)){
	if(mincost[data.cur][G[data.cur][i].to] > data.cost+1){
	  mincost[data.cur][G[data.cur][i].to] = data.cost+1;
	  Q.push(Data(data.cur,G[data.cur][i].to,data.cost+1,data.dist+dist));
	}
      } else if(mindist[data.cur][G[data.cur][i].to] > data.dist+dist){
	mindist[data.cur][G[data.cur][i].to] = data.dist + dist;
	mincost[data.cur][G[data.cur][i].to] = data.cost + 1;
	Q.push(Data(data.cur,G[data.cur][i].to,data.cost+1,data.dist+dist));
      }
    }
  }
  cout << "impossible" << endl;
}

int main(){
  while(cin >> V >> E,V|E){
    unordered_map<string,int> getIndex;
    int x,y;
    string name,p,q;
    ps.clear();
    rep(i,V)G[i].clear();

    rep(i,V){
      cin >> name >> x >> y;
      getIndex[name] = (int)ps.size();
      ps.push_back(Point(x,y));
    }

    rep(i,E){
      cin >> p >> q;
      int node1 = getIndex[p], node2 = getIndex[q];
      G[node1].push_back(Edge(node1,node2,getDist(ps[node1],ps[node2])));
      G[node2].push_back(Edge(node2,node1,getDist(ps[node1],ps[node2])));
    }

    cin >> p >> q;
    sp = getIndex[p], gp = getIndex[q];
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 28124
final_rank: 15

code_snippet: /*
02:08 - 04:05
 */

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<unordered_map>
#include<queue>
#include<climits>

#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 MAX 2000
#define pow2(a) ((a)*(a))
#define EPS 1e-7
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

struct Point{
  double x,y;
  Point(double x=IINF,double y=IINF):x(x),y(y){}
  Point operator - (const Point& a)const { return {x-a.x,y-a.y}; }
};

struct Edge{
  int from,to;
  double dist;
  Edge(int from=IINF,int to=IINF,double dist=IINF):from(from),to(to),dist(dist){}
};

struct Data{
  int pre,cur,cost;
  double dist;
  Data(int pre=IINF,int cur=IINF,int cost=IINF,double dist=IINF):pre(pre),cur(cur),cost(cost),dist(dist){}
  bool operator < (const Data& a) const {
    if(equals(dist,a.dist))return cost > a.cost;
    return dist > a.dist;
  }
};

inline double getDist(Point a,Point b){ return sqrt(pow2(a.x-b.x)+pow2(a.y-b.y)); }
inline double cross(Point a,Point b){ return a.x*b.y-a.y*b.x; }

vector<Edge> G[MAX];
vector<Point> ps;
double mindist[MAX][MAX];//mindist[pre_node][cur_node] 
int    mincost[MAX][MAX];
int E,V,sp,gp;

void compute(){

  rep(i,V)rep(j,V){
    mindist[i][j] = IINF;
    mincost[i][j] = IINF;
  }
  priority_queue<Data> Q;
  rep(i,G[sp].size()){
    mindist[sp][G[sp][i].to] = G[sp][i].dist;
    mincost[sp][G[sp][i].to] = 2;
    Q.push(Data(sp,G[sp][i].to,2,G[sp][i].dist));
  }

  while(!Q.empty()){
    Data data = Q.top(); Q.pop();
    Point cp = ps[data.cur];
    Point pp = ps[data.pre];

    if(data.cur == gp){ cout << data.cost << endl; return; }

    rep(i,G[data.cur].size()){
      int next = i;
      Point np = ps[G[data.cur][next].to];
      if(G[data.cur][next].to == data.pre)continue;
      if(cross(cp-pp,np-pp) < -EPS)continue;
      double dist = G[data.cur][next].dist;
      if(equals(mindist[data.cur][next],data.dist+dist)){
	if(mincost[data.cur][G[data.cur][next].to] > data.cost+1){
	  mincost[data.cur][G[data.cur][next].to] = data.cost+1;
	  Q.push(Data(data.cur,G[data.cur][next].to,data.cost+1,data.dist+dist));
	}
      } else if(mindist[data.cur][G[data.cur][next].to] > data.dist+dist){
	mindist[data.cur][G[data.cur][next].to] = data.dist + dist;
	mincost[data.cur][G[data.cur][next].to] = data.cost + 1;
	Q.push(Data(data.cur,G[data.cur][next].to,data.cost+1,data.dist+dist));
      }
    }
  }

  cout << "impossible" << endl;

}

int main(){
  while(cin >> V >> E,V|E){
    unordered_map<string,int> getIndex;
    int x,y;
    string name,p,q;
    ps.clear();
    rep(i,V)G[i].clear();

    rep(i,V){
      cin >> name >> x >> y;
      getIndex[name] = (int)ps.size();
      ps.push_back(Point(x,y));
    }

    rep(i,E){
      cin >> p >> q;
      int node1 = getIndex[p], node2 = getIndex[q];
      G[node1].push_back(Edge(node1,node2,getDist(ps[node1],ps[node2])));
      G[node2].push_back(Edge(node2,node1,getDist(ps[node1],ps[node2])));
    }

    cin >> p >> q;
    sp = getIndex[p], gp = getIndex[q];

    compute();

  }
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 28124
final_rank: 16

code_snippet: /*
02:08 - 
 */

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<unordered_map>
#include<queue>
#include<climits>
#include<cassert>

#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 MAX 2000
#define pow2(a) ((a)*(a))
#define EPS 1e-7
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

struct Point{
  double x,y;
  Point(double x=IINF,double y=IINF):x(x),y(y){}
  Point operator - (const Point& a)const { return {x-a.x,y-a.y}; }
};

struct Edge{
  int from,to;
  double dist;
  Edge(int from=IINF,int to=IINF,double dist=IINF):from(from),to(to),dist(dist){}
};

struct Data{
  int pre,cur,cost;
  double dist;
  Data(int pre=IINF,int cur=IINF,int cost=IINF,double dist=IINF):pre(pre),cur(cur),cost(cost),dist(dist){}
  bool operator < (const Data& a) const {
    if(equals(dist,a.dist))return cost > a.cost;
    return dist > a.dist;
  }
};

inline double getDist(Point a,Point b){ return sqrt(pow2(a.x-b.x)+pow2(a.y-b.y)); }
inline double cross(Point a,Point b){ return a.x*b.y-a.y*b.x; }


vector<Edge> G[MAX];
vector<Point> ps;
double mindist[MAX][MAX];//mindist[pre_node][cur_node] 
int    mincost[MAX][MAX];
int E,V,sp,gp;

bool cmp(const Edge& a,const Edge& b){
  Point A = ps[a.to]-ps[a.from], B = ps[b.to]-ps[b.from];
  return atan2(A.y,A.x) < atan2(B.y,B.x);
}

void compute(){

  rep(i,V)rep(j,V){
    mindist[i][j] = IINF;
    mincost[i][j] = IINF;
  }
  priority_queue<Data> Q;
  rep(i,G[sp].size()){
    mindist[sp][G[sp][i].to] = G[sp][i].dist;
    mincost[sp][G[sp][i].to] = 2;
    Q.push(Data(sp,G[sp][i].to,2,G[sp][i].dist));
  }

  while(!Q.empty()){
    Data data = Q.top(); Q.pop();
    Point cp = ps[data.cur];
    Point pp = ps[data.pre];
    //cout << "cur | (" << data.pre << "," << data.cur << "," << data.cost << "," << data.dist << ")" << endl;
    if(data.cur == gp){
      cout << data.cost << endl;
      return;
    }

    rep(i,G[data.cur].size()){
      //cout << "cand " << G[data.cur][i].to << endl;
      //if(G[data.cur][i].from == data.cur && G[data.cur][i].to == data.pre){
      //int next = (i+(int)G[data.cur].size()-1)%(int)G[data.cur].size();
      int next = i;
	Point np = ps[G[data.cur][next].to];
	//if(equals(pp.x,np.x) || equals(pp.y,np.y))continue;
	//cout << "cand is ok" << endl;
	if(G[data.cur][next].to == data.pre)continue;
	//cout << G[data.cur][next].to << "here" << endl;
	if(cross(cp-pp,np-pp) < -EPS)continue;
	//cout << "ok" << endl;
	double dist = G[data.cur][next].dist;
	if(equals(mindist[data.cur][next],data.dist+dist)){
	  if(mincost[data.cur][G[data.cur][next].to] > data.cost+1){
	    //cout << "go next " << data.cur << " to " << G[data.cur][next].to << endl;
	    mincost[data.cur][G[data.cur][next].to] = data.cost+1;
	    Q.push(Data(data.cur,G[data.cur][next].to,data.cost+1,data.dist+dist));
	  }
	} else if(mindist[data.cur][G[data.cur][next].to] > data.dist+dist){
	  //cout << "go next " << data.cur << " to " << G[data.cur][next].to << endl;
	  mindist[data.cur][G[data.cur][next].to] = data.dist + dist;
	  mincost[data.cur][G[data.cur][next].to] = data.cost + 1;
	  Q.push(Data(data.cur,G[data.cur][next].to,data.cost+1,data.dist+dist));
	}
	//}
    }
  }

  cout << "impossible" << endl;

}

int main(){
  while(cin >> V >> E,V|E){
    unordered_map<string,int> getIndex;
    int x,y;
    string name,p,q;
    ps.clear();
    rep(i,V)G[i].clear();

    rep(i,V){
      cin >> name >> x >> y;
      getIndex[name] = (int)ps.size();
      ps.push_back(Point(x,y));
    }
    assert(getIndex.size() == ps.size());

    rep(i,E){
      cin >> p >> q;
      int node1 = getIndex[p], node2 = getIndex[q];
      G[node1].push_back(Edge(node1,node2,getDist(ps[node1],ps[node2])));
      G[node2].push_back(Edge(node2,node1,getDist(ps[node1],ps[node2])));
    }

    cin >> p >> q;
    sp = getIndex[p], gp = getIndex[q];

    rep(i,V)sort(G[i].begin(),G[i].end(),cmp);


    /*
    cout << "------------" << endl;
    rep(i,V){
      cout << i << " node---" << endl;
      rep(j,G[i].size()){
	cout << "(" << G[i][j].from << "," << G[i][j].to << "," << G[i][j].dist << ") ";
      }
      cout << endl;
    }
    cout << "goto Compute" << endl << endl;
    */
    compute();

  }
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 28144
final_rank: 17

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <map>
#include <string>
using namespace std;

const int INF = 1<<29;

typedef pair<int,int> P;

class State{
public:
  int cost,node,x,y,dir,now;

  State(int c, int n, int _x, int _y, int d, int n2){
    cost = c;
    node = n;
    x = _x;
    y = _y;
    dir = d;
    now = n2;
  }

  bool operator < (const State& s) const {
    if(cost == s.cost) return node > s.node;
    return cost > s.cost;
  }
};

int V,E;
vector<int> G[1001];
vector<P>v;
P d[1001][4];

void dijkstra(int s){
  priority_queue<State>que;
  int X = v[s].first, Y = v[s].second;
  for(int i=0; i<4; i++){
    State t(0,1,X,Y,i,s);
    d[s][i].first = d[s][i].second = 0;
    que.push(t);
  }

  while(!que.empty()){
    State tmp = que.top();
    que.pop();
    int cost = tmp.cost;
    int x = tmp.x, y = tmp.y;
    int node = tmp.node;
    int dir = tmp.dir;
    int now = tmp.now;

    if(d[now][dir].first < cost) continue;

    for(int i=0; i<G[now].size(); i++){
      int index = G[now][i];
      int nx = v[index].first, ny = v[index].second;
      if(dir == 0 && y == ny && x > nx){
	if(d[index][3].first >= cost + x - nx){
	  d[index][3].first = cost + x - nx;
	  d[index][3].second = min(d[index][3].second,node + 1);
	  que.push(State(d[index][3].first,d[index][3].second,nx,ny,3,index));
	}
      }

      if(dir == 1 && x == nx && y < ny){
	if(d[index][0].first >= cost + ny - y){
	  d[index][0].first = cost + ny - y;
	  d[index][0].second = min(d[index][0].second,node + 1);
	  que.push(State(d[index][0].first,d[index][0].second,nx,ny,0,index));
	}
      }

      if(dir == 2 && y == ny && x < nx){

	if(d[index][1].first >= cost + nx - x){
	  d[index][1].first = cost + nx - x;
	  d[index][1].second = min(d[index][1].second,node + 1);
	  que.push(State(d[index][1].first,d[index][1].second,nx,ny,1,index));
	}
      }

      if(dir == 3 && x == nx && y > ny){
	if(d[index][2].first >= cost + y - ny){
	  d[index][2].first = cost + y - ny;
	  d[index][2].second = min(d[index][2].second,node + 1);
	  que.push(State(d[index][2].first,d[index][2].second,nx,ny,2,index));
	}
      }


      //straight

      if(dir == 0 && nx == x && ny > y){
	if(d[index][dir].first >= cost + ny - y){
	  d[index][dir].first = cost + ny - y;
	  d[index][dir].second = min(d[index][dir].second,node + 1);
	  que.push(State(d[index][dir].first,d[index][dir].second,nx,ny,dir,index));
	}
      }

      if(dir == 1 && ny == y && nx > x){
	if(d[index][dir].first >= cost + nx - x){
	  d[index][dir].first = cost + nx - x;
	  d[index][dir].second = min(d[index][dir].second,node + 1);
	  que.push(State(d[index][dir].first,d[index][dir].second,nx,ny,dir,index));
	}
      }
      
      if(dir == 2 && nx == x && ny < y){
	if(d[index][dir].first >= cost + y - ny){
	  d[index][dir].first = cost + y - ny;
	  d[index][dir].second = min(d[index][dir].second,node + 1);
	  que.push(State(d[index][dir].first,d[index][dir].second,nx,ny,dir,index));
	}
      }
      
      if(dir == 3 && ny == y && nx < x){
	if(d[index][dir].first >= cost + x - nx){
	  d[index][dir].first = cost + x - nx;
	  d[index][dir].second = min(d[index][dir].second,node + 1);
	  que.push(State(d[index][dir].first,d[index][dir].second,nx,ny,dir,index));
	}

      }

    }
  }
}
int main(){

  while(cin >> V >> E,V|E){

    for(int i=0; i<1001; i++)
      for(int j=0; j<4; j++) d[i][j].first = d[i][j].second = INF;

    for(int i=0; i<1001; i++)G[i].clear();
    v.clear();

    string s;
    int x,y;
    map<string,int>m;
    for(int i=0; i<V; i++){
      cin >> s >> x >> y;
      v.push_back(P(x,y));
      m[s] = i;
    }

    string from,to;
    for(int i=0; i<E; i++){
      cin >> from >> to;
      G[m[from]].push_back(m[to]);
      G[m[to]].push_back(m[from]);
    }

    string start,des;
    cin >> start >> des;

    dijkstra(m[start]);

    int MinCost = INF, ans = INF;

    for(int i=0; i<4; i++){
      if(MinCost > d[m[des]][i].first){
	MinCost = d[m[des]][i].first;
	ans = d[m[des]][i].second;
      } else if(MinCost == d[m[des]][i].first){
	ans = min(ans,d[m[des]][i].second);
      }
    }

    if(MinCost == INF) cout << "impossible" << endl;
    else cout << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 1548
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <cassert>
using namespace std;

const int MAXM = 1001;
const int INF = 1<<28;
int M, N;
map<string,int> id;
int px[MAXM], py[MAXM];
vector<int> G[MAXM];
pair<int,int> cost[4][MAXM];

struct State {
  int d, v;
  pair<int,int> cost;
  bool operator < (const State &s) const {
    return cost > s.cost;
  }
};

int getDir(int prev, int now) {
  int dx = px[now] - px[prev];
  int dy = py[now] - py[prev];
  assert(dx == 0 && dy != 0 || dx != 0 && dy == 0);
  if(dx >=  1) return 0;
  if(dy >=  1) return 1;
  if(dx <= -1) return 2;
  if(dy <= -1) return 3;
  assert(false);
  return -1;
}

int getDist(int prev, int now) {
  int dx = px[now] - px[prev];
  int dy = py[now] - py[prev];
  return abs(dx) + abs(dy);
}

int bfs(int src, int dst) {
  fill(cost[0], cost[4], make_pair(INF,INF));
  cost[0][src] = make_pair(0,0);
  cost[1][src] = make_pair(0,0);
  cost[2][src] = make_pair(0,0);

  cost[3][src] = make_pair(0,0);
  priority_queue<State> que;
  que.push((State){0,src,make_pair(0,0)});
  que.push((State){1,src,make_pair(0,0)});
  que.push((State){2,src,make_pair(0,0)});
  que.push((State){3,src,make_pair(0,0)});
  while(que.size()) {
    State s = que.top();
    que.pop();
    if(cost[s.d][s.v] != s.cost) continue;
    if(s.v == dst) return s.cost.second;
    for(int k = 0; k < G[s.v].size(); ++k) {
      int nv = G[s.v][k];
      int nd = getDir(s.v, nv);
      pair<int,int> ncost
        = make_pair(s.cost.first + getDist(s.v, nv), s.cost.second + 1);
      if((nd-s.d+4)%4 > 1) continue;
      if(cost[nd][nv] < ncost) continue;
      cost[nd][nv] = ncost;
      que.push((State){nd, nv, ncost});
    }
  }
  return INF;
}

int main() {
  while(cin >> M >> N && (M|N)) {
    fill(G, G+MAXM, vector<int>());
    id.clear();
    for(int i = 0; i < M; ++i) {
      string s;
      cin >> s >> px[i] >> py[i];
      id[s] = i;
    }
    for(int i = 0; i < N; ++i) {
      string s, t;
      cin >> s >> t;
      G[id[s]].push_back(id[t]);
      G[id[t]].push_back(id[s]);
    }
    string src, dst;
    cin >> src >> dst;
    int res = bfs(id[src], id[dst]);
    if(res == INF) cout << "impossible" << endl;
    else cout << res+1 << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 1536
final_rank: 8

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>
#include <iomanip>
#include <fstream>
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()
const int INF = 1<<29;
typedef long long ll;
typedef pair<int,int> pii;

int X[1000];
int Y[1000];

int dir(int a, int b) {
  if (X[a] == X[b]) {
    if (Y[a] < Y[b]) return 0;
    else return 2;
  } else {
    if (X[a] < X[b]) return 1;
    else return 3;
  }
}
int dis(int a, int b) {
  return abs(X[a]-X[b]) + abs(Y[a]-Y[b]);
}

struct P {
  int now, d, cost, len;
  P(int now, int d, int cost, int len) :
    now(now),d(d),cost(cost),len(len) {}
  bool operator<(const P &b) const {
    return cost != b.cost ? cost > b.cost : len > b.len;
  }
};

pii g[1000][4];
int dist[1000][4];
string name[1000];

int main() {
  int m,n;
  while(cin>>m>>n,m||n) {
    map<string,int> mp;
    REP(i,m) {
      cin >> name[i] >> X[i] >> Y[i];
      mp[name[i]] = i;
    }
    REP(i,m)REP(j,4) g[i][j]=pii(-1,0);
    REP(i,n) {
      string s,t;
      cin >> s >> t;
      int a = mp[s];
      int b = mp[t];
      g[a][dir(a,b)] = pii(b,dis(a,b));
      g[b][dir(b,a)] = pii(a,dis(a,b));
    }
    string s, t;
    cin >> s >> t;
    int start = mp[s];
    int end = mp[t];
    priority_queue<P> Q;
    REP(i,m)REP(j,4) dist[i][j] = INF;
    REP(i,4) {
      Q.push(P(start,i,0,1));
      dist[start][i] = 0;
    }
    int ans = INF;
    while(!Q.empty()) {
      P p = Q.top(); Q.pop();
      
      int nd = (p.d+3) % 4;
      int now = p.now;

      if (dist[now][p.d] > p.cost) continue;
      
      int dd[2] = {p.d,nd};

//      cout << now << " " << p.d << endl;
      if (now == end) {
        ans = p.len;
        break;
      }
      
      REP(i,2) {
        pii e = g[now][dd[i]];
        int b = e.first;
        if (b != -1) {
          int nd = dist[now][p.d] + e.second;
          if (dist[b][dd[i]] > nd) {
            dist[b][dd[i]] = nd;
            Q.push(P(b,dd[i],nd,p.len+1));
          }
        }
      }
    }
    if (ans == INF) cout << "impossible" << endl;
    else cout << ans << endl;
  }
}
accuracy: 1
time_ms: 60
memory_kb: 1448
final_rank: 2

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)n; ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cout<<*i<<" "; cout<<endl; }

typedef long long ll;
const int INF = 1e8;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<int, int> P;

P operator -(P p, P q){
  return P(p.first - q.first, p.second - q.second);
}

inline int distP(P p, P q){
  if(p.first == q.first) return abs(p.second - q.second);
  else return abs(p.first - q.first);
  //return abs(p.first - q.first) + abs(p.second - q.second);
}

inline int inner(P p, P q){
  return p.first * q.first + p.second * q.second;
}
inline int cross(P p, P q){
  return p.first * q.second - p.second * q.first;
}

inline bool ok(P p, P q){
  //assert(p.first == 0 || p.second == 0);
  //assert(q.first == 0 || q.second == 0);
  return (inner(p, q) > 0 && cross(p, q) == 0) || (inner(p, q) == 0 && cross(p, q) > 0);
}

int main(){
  assert(P(3, 1) - P(2, 10) == P(1, -9));
  assert(!ok(P(2, 0), P(0, -2)));
  assert(!ok(P(2, 0), P(-2, 0)));
  assert(ok(P(2, 0), P(2, 0)));
  assert(ok(P(2, 0), P(0, 2)));
  int M, N;
  while(cin>>M>>N && M){
    map<string, int> id_inter;
    vector<P> inter_p(M);
    REP(i, M){
      string inter; int x, y;
      cin>>inter>>x>>y;
      int t = i;
      //int t = id_inter.size();
      id_inter[inter] = t;
      inter_p[t] = P(x, y);
    }
    vector<int> connect[1000];
    REP(i, N){
      string inter1, inter2;
      cin>>inter1>>inter2;
      int id1 = id_inter[inter1];
      int id2 = id_inter[inter2];
      connect[id1].push_back(id2);
      connect[id2].push_back(id1);
    }
    string src, dst; cin>>src>>dst;
    int from = id_inter[src];
    int to = id_inter[dst];
    P dist[1000][1000];
    REP(i, M)REP(j, M) dist[i][j] = P(-1, -1);
    queue<P> que;
    FORIT(it, connect[from]){
      que.push(P(from, *it));
      dist[from][*it] = P(distP(inter_p[from], inter_p[*it]), 2);
    }
    P ans = P(INF, INF);
    while(!que.empty()){
      P p = que.front(); que.pop();
      P state = dist[p.first][p.second];
      if(p.second == to){
        ans = min(ans, state);
      }
      FORIT(it, connect[p.second]){
        P p1 = inter_p[p.second] - inter_p[p.first];
        P p2 = inter_p[*it] - inter_p[p.second];
        if(ok(p1, p2)){
          P next = P(state.first + distP(P(0, 0), p2), state.second + 1);
          if(dist[p.second][*it] != P(-1, -1) && dist[p.second][*it] <= next){
            continue;
          }
          dist[p.second][*it] = next;
          que.push(P(p.second, *it));
        }
      }
    }
    if(ans != P(INF, INF)) cout<<ans.second<<endl;
    else cout<<"impossible"<<endl;
    assert(id_inter.size() == M);
  }
  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 9264
final_rank: 12

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)n; ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cout<<*i<<" "; cout<<endl; }

typedef long long ll;
const int INF = 1e8;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<int, int> P;

P operator -(P p, P q){
  return P(p.first - q.first, p.second - q.second);
}

inline int distP(P p, P q){
  return abs(p.first - q.first) + abs(p.second - q.second);
}

inline int inner(P p, P q){
  return p.first * q.first + p.second * q.second;
}
inline int cross(P p, P q){
  return p.first * q.second - p.second * q.first;
}

inline bool ok(P p, P q){
  //assert(p.first == 0 || p.second == 0);
  //assert(q.first == 0 || q.second == 0);
  return (inner(p, q) > 0 && cross(p, q) == 0) || (inner(p, q) == 0 && cross(p, q) > 0);
}

int main(){
  assert(P(3, 1) - P(2, 10) == P(1, -9));
  assert(!ok(P(2, 0), P(0, -2)));
  assert(!ok(P(2, 0), P(-2, 0)));
  assert(ok(P(2, 0), P(2, 0)));
  assert(ok(P(2, 0), P(0, 2)));
  int M, N;
  while(cin>>M>>N && M){
    map<string, int> id_inter;
    vector<P> inter_p(M);
    REP(i, M){
      string inter; int x, y;
      cin>>inter>>x>>y;
      int t = i;
      //int t = id_inter.size();
      id_inter[inter] = t;
      inter_p[t] = P(x, y);
    }
    vector<int> connect[1000];
    REP(i, N){
      string inter1, inter2;
      cin>>inter1>>inter2;
      int id1 = id_inter[inter1];
      int id2 = id_inter[inter2];
      connect[id1].push_back(id2);
      connect[id2].push_back(id1);
    }
    string src, dst; cin>>src>>dst;
    int from = id_inter[src];
    int to = id_inter[dst];
    P dist[1000][1000];
    REP(i, M)REP(j, M) dist[i][j] = P(-1, -1);
    queue<P> que;
    FORIT(it, connect[from]){
      que.push(P(from, *it));
      dist[from][*it] = P(distP(inter_p[from], inter_p[*it]), 2);
    }
    P ans = P(INF, INF);
    while(!que.empty()){
      P p = que.front(); que.pop();
      P state = dist[p.first][p.second];
      if(p.second == to){
        ans = min(ans, state);
      }
      FORIT(it, connect[p.second]){
        P p1 = inter_p[p.second] - inter_p[p.first];
        P p2 = inter_p[*it] - inter_p[p.second];
        if(ok(p1, p2)){
          P next = P(state.first + distP(P(0, 0), p2), state.second + 1);
          if(dist[p.second][*it] != P(-1, -1) && dist[p.second][*it] <= next){
            continue;
          }
          dist[p.second][*it] = next;
          que.push(P(p.second, *it));
        }
      }
    }
    if(ans != P(INF, INF)) cout<<ans.second<<endl;
    else cout<<"impossible"<<endl;
    assert(id_inter.size() == M);
  }
  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 9260
final_rank: 10

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)n; ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cout<<*i<<" "; cout<<endl; }

typedef long long ll;
const int INF = 1e8;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<int, int> P;

P operator -(P p, P q){
  return P(p.first - q.first, p.second - q.second);
}

int distP(P p, P q){
  return abs(p.first - q.first) + abs(p.second - q.second);
}

int inner(P p, P q){
  return p.first * q.first + p.second * q.second;
}
int cross(P p, P q){
  return p.first * q.second - p.second * q.first;
}

bool ok(P p, P q){
  assert(p.first == 0 || p.second == 0);
  assert(q.first == 0 || q.second == 0);
  return (inner(p, q) > 0 && cross(p, q) == 0) || (inner(p, q) == 0 && cross(p, q) > 0);
}

int main(){
  assert(P(3, 1) - P(2, 10) == P(1, -9));
  assert(!ok(P(2, 0), P(0, -2)));
  assert(!ok(P(2, 0), P(-2, 0)));
  assert(ok(P(2, 0), P(2, 0)));
  assert(ok(P(2, 0), P(0, 2)));
  int M, N;
  while(cin>>M>>N && M){
    map<string, int> id_inter;
    vector<P> inter_p(M);
    REP(i, M){
      string inter; int x, y;
      cin>>inter>>x>>y;
      int t = i;
      //int t = id_inter.size();
      id_inter[inter] = t;
      inter_p[t] = P(x, y);
    }
    vector<int> connect[1000];
    REP(i, N){
      string inter1, inter2;
      cin>>inter1>>inter2;
      int id1 = id_inter[inter1];
      int id2 = id_inter[inter2];
      connect[id1].push_back(id2);
      connect[id2].push_back(id1);
    }
    string src, dst; cin>>src>>dst;
    int from = id_inter[src];
    int to = id_inter[dst];
    P dist[1000][1000];
    REP(i, M)REP(j, M) dist[i][j] = P(-1, -1);
    queue<P> que;
    FORIT(it, connect[from]){
      que.push(P(from, *it));
      dist[from][*it] = P(distP(inter_p[from], inter_p[*it]), 2);
    }
    P ans = P(INF, INF);
    while(!que.empty()){
      P p = que.front(); que.pop();
      P state = dist[p.first][p.second];
      if(p.second == to){
        ans = min(ans, state);
      }
      FORIT(it, connect[p.second]){
        P p1 = inter_p[p.second] - inter_p[p.first];
        P p2 = inter_p[*it] - inter_p[p.second];
        if(ok(p1, p2)){
          P next = P(state.first + distP(P(0, 0), p2), state.second + 1);
          if(dist[p.second][*it] != P(-1, -1) && dist[p.second][*it] <= next){
            continue;
          }
          dist[p.second][*it] = next;
          que.push(P(p.second, *it));
        }
      }
    }
    if(ans != P(INF, INF)) cout<<ans.second<<endl;
    else cout<<"impossible"<<endl;
    assert(id_inter.size() == M);
  }
  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 9260
final_rank: 10

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

const int INF = INT_MAX / 2;

class Edge
{
public:
    int to, cost;
    Edge(){};
    Edge(int to0, int cost0){to = to0; cost = cost0;}
};

int main()
{
    for(;;){
        int n, m;
        cin >> n >> m;
        if(n == 0)
            return 0;

        map<string, int> index;
        vector<int> x(n), y(n);
        for(int i=0; i<n; ++i){
            string s;
            cin >> s >> x[i] >> y[i];
            index[s] = i;
        }

        vector<vector<Edge> > edges(n, vector<Edge>(4, Edge(-1, -1)));
        for(int i=0; i<m; ++i){
            string s, t;
            cin >> s >> t;
            int a = index[s];
            int b = index[t];
            int d;
            if(x[b] > x[a])
                d = 0;
            else if(y[b] < y[a])
                d = 1;
            else if(x[b] < x[a])
                d = 2;
            else
                d = 3;
            edges[a][d] = Edge(b, abs(x[a] - x[b]) + abs(y[a] - y[b]));
            edges[b][(d+2)%4] = Edge(a, abs(x[a] - x[b]) + abs(y[a] - y[b]));
        }

        string startName, goalName;
        cin >> startName >> goalName;
        int start = index[startName];
        int goal = index[goalName];

        vector<vector<pair<int, int> > > dp(n, vector<pair<int, int> >(4, make_pair(INF, INF)));
        multimap<pair<int, int>, pair<int, int> > mm;
        for(int i=0; i<4; ++i){
            dp[start][i] = make_pair(0, 1);
            mm.insert(make_pair(make_pair(0, 1), make_pair(start, i)));
        }

        while(!mm.empty()){
            pair<int, int> cost = mm.begin()->first;
            int pos = mm.begin()->second.first;
            int d = mm.begin()->second.second;
            mm.erase(mm.begin());
            if(cost > dp[pos][d])
                continue;

            for(int i=0; i<2; ++i){
                int d2 = (d + 4 - i) % 4;
                pair<int, int> cost2(cost.first + edges[pos][d2].cost, cost.second + 1);
                int next = edges[pos][d2].to;
                if(next == -1)
                    continue;

                if(cost2 < dp[next][d2]){
                    dp[next][d2] = cost2;
                    mm.insert(make_pair(cost2, make_pair(next, d2)));
                }
            }
        }

        pair<int, int> ret(INF, INF);
        for(int i=0; i<4; ++i)
            ret = min(ret, dp[goal][i]);
        if(ret.first == INF)
            cout << "impossible" << endl;
        else
            cout << ret.second << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 1516
final_rank: 3