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

const int inf = (int)1e9;

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

struct Path{
  int cost;
  vector<int> nodes;
  Path(){}
  Path(int _cost, const vector<int> &_nodes) : cost(_cost), nodes(_nodes) {}
  void print() const{
    for(size_t i = 0; i < nodes.size(); i++)
      cout << nodes[nodes.size()- i - 1] + 1 << (i + 1 == nodes.size() ? '\n' : '-');
  }
  bool empty() const {return nodes.size() == 0; }
};


bool operator<(const Path &p1, const Path &p2) {
  if(p1.cost != p2.cost){
    return p1.cost > p2.cost;
  }else{
    int pos1 = p1.nodes.size();
    int pos2 = p2.nodes.size();
    while(--pos1 >= 0 && --pos2 >= 0 && p1.nodes[pos1] == p2.nodes[pos2]);
    if(p1.nodes[pos1] != p2.nodes[pos2]){
      return p1.nodes[pos1] > p2.nodes[pos2];
    }else{
      return pos1 > pos2;
    }
  }
}

Path operator+(const Path &p1, const Path &p2){
  assert(!p1.empty() && !p2.empty() && p1.nodes.back() == p2.nodes[0]);
  vector<int> nodes = p1.nodes;
  for(size_t i = 1; i < p2.nodes.size(); i++){
    nodes.push_back(p2.nodes[i]);
  }
  return Path(p1.cost + p2.cost, nodes);
}

typedef vector<vector<edge> > Graph;

Path make_path(const Graph &graph, int s, int t,
               const vector<int> &prevv,
               const vector<int> &preve){
  int cost = 0;
  vector<int> nodes;
  for(int v = t; s != v; v = prevv[v]){
    nodes.push_back(v);
    cost += graph[prevv[v]][preve[v]].cost;
  }
  
  nodes.push_back(s);
  reverse(nodes.begin(), nodes.end());
  return Path(cost, nodes);
}


Path dijkstra(const Graph &graph, int s, int t,
              vector<int> *ignored_nodes = NULL,
              vector<int> *ignored_edges = NULL){
  
  int n = graph.size();
  vector<int> dist(n, inf);
  vector<int> prevv(n, inf);
  vector<int> preve(n, inf);
  vector<int> ig_edges(n, 0);
  
  if(ignored_nodes){
    for(size_t i = 0; i < ignored_nodes->size(); i++){
      dist[(*ignored_nodes)[i]] = -inf;
    }
  }
  
  if(ignored_edges){
    for(size_t i = 0; i < ignored_edges->size(); i++){
      ig_edges[(*ignored_edges)[i]] = 1;
    }
  }

  
  priority_queue<pair<int, int> > que;
  dist[s] = 0;  
  que.push(make_pair(0, s));
  
  while(!que.empty()){
    pair<int, int> p = que.top();  que.pop();
    int cost = -p.first;
    int v = p.second;
    
    if(cost > dist[v]) continue;
    // shortest path found
    
    if(v == t){
      return make_path(graph, s, t, prevv, preve);
    }
    
    for(size_t i = 0; i < graph[v].size(); i++){
      const edge &e = graph[v][i];
      int tmp = e.cost + dist[v];
      if(v == s && ig_edges[i]) continue; // e is ignored edge
      if(tmp < dist[e.to] || (tmp == dist[e.to] && v < prevv[e.to])){
        dist[e.to] = tmp;
        prevv[e.to] = v;
        preve[e.to] = i;
        que.push(make_pair(-tmp, e.to));
      }
    }
  }
  // unfound
  return Path();
}

class PsuedoTree{
  struct node_t{
    int v;
    map<int, node_t*> ch;
    node_t(int s) : v(s) {}
    ~node_t(){
      for(map<int, node_t*>::iterator iter = ch.begin(); iter != ch.end(); iter++){
        delete iter->second;
      }
    }
  };
  
  node_t *root;
public:
  PsuedoTree(const Path &p){
    assert(!p.empty());
    root = new node_t(p.nodes[0]);
    add_path(p);
  }
  
  ~PsuedoTree(){ delete root; }
  
  void add_path(const Path &p){
    node_t *t = root;
    const vector<int> &nodes = p.nodes;
    assert(nodes[0] == t->v);
    
    vector<int> ignored_nodes;
    
    for(size_t i = 1; i < p.nodes.size(); i++){
      if(t->ch.find(nodes[i]) == t->ch.end()){
        t->ch[nodes[i]] = new node_t(nodes[i]);
      }
      t = t->ch[nodes[i]];
      
    }
  }
  
  void generate_candidate_path(const Graph &graph, int s, int t,
                               const Path &p,
                               priority_queue<Path> &path_que){
    int sum = 0;
    node_t *pt_node = root;
    vector<int> ignored_nodes;
    
    for(size_t i = 0; i + 1 < p.nodes.size(); i++){
      int v = p.nodes[i];
      vector<int> ignored_edges;
      
      for(size_t j = 0; j < graph[v].size(); j++){      
        if(pt_node->ch.find(graph[v][j].to) != pt_node->ch.end()){
          ignored_edges.push_back(j);
        }
      }
      
      ignored_nodes.push_back(v);
      Path candidate_path = dijkstra(graph, v, t, &ignored_nodes, &ignored_edges);
      if(!candidate_path.empty()){
        candidate_path = Path(sum, ignored_nodes) +  candidate_path;
        add_path(candidate_path);
        path_que.push(candidate_path);
      }
      
      pt_node = pt_node->ch[p.nodes[i+1]];
      assert(pt_node != NULL);
      
      for(size_t j = 0; j < graph[v].size(); j++)
        if(graph[v][j].to == p.nodes[i+1]) 
          sum += graph[v][j].cost;
    }
  }
};


vector<Path> topKShortestPath(const Graph &graph, int s, int t, int k){
  vector<Path> kshort(k);

  // cerr << "start computation" << endl;
  Path p = dijkstra(graph, s, t);
  if(p.empty()) return vector<Path>();
  
  PsuedoTree pt(p);
  priority_queue<Path> path_que;
  
  path_que.push(p);
  for(int i = 0; i < k; i++){
    if(path_que.empty()) return vector<Path>();

    kshort[i] = path_que.top(); path_que.pop();
    pt.generate_candidate_path(graph, s, t, kshort[i], path_que);
  }
  
  return kshort;
}
  

int main(){
  int n, m, k, a, b, x, y, d;
  while(cin >> n >> m >> k >> a >> b && (n + m + k + a + b) > 0){
    
    Graph g(n);
    for(int i = 0; i < m; i++){
      cin >> x >> y >> d;
      x--, y--;
      g[y].push_back(edge(x, d));
    }

    vector<Path> paths = topKShortestPath(g, --b, --a, k);
    if(paths.size() == 0){
      cout << "None" << endl;
    }else{
      paths[k-1].print();
    }
  }
  return 0;
}
### Prompt

Construct a cpp code solution to the problem outlined:

Isaac is tired of his daily trip to his ofice, using the same shortest route everyday. Although this saves his time, he must see the same scenery again and again. He cannot stand such a boring commutation any more.

One day, he decided to improve the situation. He would change his route everyday at least slightly. His new scheme is as follows. On the first day, he uses the shortest route. On the second day, he uses the second shortest route, namely the shortest except one used on the first day. In general, on the k-th day, the k-th shortest route is chosen. Visiting the same place twice on a route should be avoided, of course.

You are invited to help Isaac, by writing a program which finds his route on the k-th day. The problem is easily modeled using terms in the graph theory. Your program should find the k-th shortest path in the given directed graph.



Input

The input consists of multiple datasets, each in the following format.


n    m    k    a   b
x1   y1   d1
x2   y2   d2
...
xm   ym   dm


Every input item in a dataset is a non-negative integer. Two or more input items in a line are separated by a space.

n is the number of nodes in the graph. You can assume the inequality 2 ≤ n ≤ 50. m is the number of (directed) edges. a is the start node, and b is the goal node. They are between 1 and n, inclusive. You are required to find the k-th shortest path from a to b. You can assume 1 ≤ k ≤ 200 and a ≠ b.

The i-th edge is from the node xi to yi with the length di (1 ≤ i ≤ m). Both xi and yi are between 1 and n, inclusive. di is between 1 and 10000, inclusive. You can directly go from xi to yi, but not from yi to xi unless an edge from yi to xi is explicitly given. The edge connecting the same pair of nodes is unique, if any, that is, if i ≠ j, it is never the case that xi equals xj and yi equals yj. Edges are not connecting a node to itself, that is, xi never equals yi . Thus the inequality 0 ≤ m ≤ n(n - 1) holds.

Note that the given graph may be quite unrealistic as a road network. Both the cases m = 0 and m = n(n - 1) are included in the judges' data.

The last dataset is followed by a line containing five zeros (separated by a space).

Output

For each dataset in the input, one line should be output as specified below. An output line should not contain extra characters such as spaces.

If the number of distinct paths from a to b is less than k, the string None should be printed. Note that the first letter of None is in uppercase, while the other letters are in lowercase.

If the number of distinct paths from a to b is k or more, the node numbers visited in the k-th shortest path should be printed in the visited order, separated by a hyphen (minus sign). Note that a must be the first, and b must be the last in the printed line.

In this problem the term shorter (thus shortest also) has a special meaning. A path P is defined to be shorter than Q, if and only if one of the following conditions holds.

1. The length of P is less than the length of Q. The length of a path is defined to be the sum of lengths of edges on the path.
2. The length of P is equal to the length of Q, and P's sequence of node numbers comes earlier than Q's in the dictionary order. Let's specify the latter condition more precisely. Denote P's sequence of node numbers by p1, p2,..., ps, and Q's by q1, q2,..., qt. p1 = q1 = a and ps = qt = b should be observed. The sequence P comes earlier than Q in the dictionary order, if for some r (1 ≤ r ≤ s and r ≤ t), p1 = q1,..., pr-1 = qr-1, and pr < qr (pr is numerically smaller than qr).


A path visiting the same node twice or more is not allowed.

Example

Input

5 20 10 1 5
1 2 1
1 3 2
1 4 1
1 5 3
2 1 1
2 3 1
2 4 2
2 5 2
3 1 1
3 2 2
3 4 1
3 5 1
4 1 1
4 2 1
4 3 1
4 5 2
5 1 1
5 2 1
5 3 1
5 4 1
4 6 1 1 4
2 4 2
1 3 2
1 2 1
1 4 3
2 3 1
3 4 1
3 3 5 1 3
1 2 1
2 3 1
1 3 1
0 0 0 0 0


Output

1-2-4-3-5
1-2-3-4
None

### Response

```cpp
#include <set>
#include <vector>
#include <queue>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <map>
using namespace std;

const int inf = (int)1e9;

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

struct Path{
  int cost;
  vector<int> nodes;
  Path(){}
  Path(int _cost, const vector<int> &_nodes) : cost(_cost), nodes(_nodes) {}
  void print() const{
    for(size_t i = 0; i < nodes.size(); i++)
      cout << nodes[nodes.size()- i - 1] + 1 << (i + 1 == nodes.size() ? '\n' : '-');
  }
  bool empty() const {return nodes.size() == 0; }
};


bool operator<(const Path &p1, const Path &p2) {
  if(p1.cost != p2.cost){
    return p1.cost > p2.cost;
  }else{
    int pos1 = p1.nodes.size();
    int pos2 = p2.nodes.size();
    while(--pos1 >= 0 && --pos2 >= 0 && p1.nodes[pos1] == p2.nodes[pos2]);
    if(p1.nodes[pos1] != p2.nodes[pos2]){
      return p1.nodes[pos1] > p2.nodes[pos2];
    }else{
      return pos1 > pos2;
    }
  }
}

Path operator+(const Path &p1, const Path &p2){
  assert(!p1.empty() && !p2.empty() && p1.nodes.back() == p2.nodes[0]);
  vector<int> nodes = p1.nodes;
  for(size_t i = 1; i < p2.nodes.size(); i++){
    nodes.push_back(p2.nodes[i]);
  }
  return Path(p1.cost + p2.cost, nodes);
}

typedef vector<vector<edge> > Graph;

Path make_path(const Graph &graph, int s, int t,
               const vector<int> &prevv,
               const vector<int> &preve){
  int cost = 0;
  vector<int> nodes;
  for(int v = t; s != v; v = prevv[v]){
    nodes.push_back(v);
    cost += graph[prevv[v]][preve[v]].cost;
  }
  
  nodes.push_back(s);
  reverse(nodes.begin(), nodes.end());
  return Path(cost, nodes);
}


Path dijkstra(const Graph &graph, int s, int t,
              vector<int> *ignored_nodes = NULL,
              vector<int> *ignored_edges = NULL){
  
  int n = graph.size();
  vector<int> dist(n, inf);
  vector<int> prevv(n, inf);
  vector<int> preve(n, inf);
  vector<int> ig_edges(n, 0);
  
  if(ignored_nodes){
    for(size_t i = 0; i < ignored_nodes->size(); i++){
      dist[(*ignored_nodes)[i]] = -inf;
    }
  }
  
  if(ignored_edges){
    for(size_t i = 0; i < ignored_edges->size(); i++){
      ig_edges[(*ignored_edges)[i]] = 1;
    }
  }

  
  priority_queue<pair<int, int> > que;
  dist[s] = 0;  
  que.push(make_pair(0, s));
  
  while(!que.empty()){
    pair<int, int> p = que.top();  que.pop();
    int cost = -p.first;
    int v = p.second;
    
    if(cost > dist[v]) continue;
    // shortest path found
    
    if(v == t){
      return make_path(graph, s, t, prevv, preve);
    }
    
    for(size_t i = 0; i < graph[v].size(); i++){
      const edge &e = graph[v][i];
      int tmp = e.cost + dist[v];
      if(v == s && ig_edges[i]) continue; // e is ignored edge
      if(tmp < dist[e.to] || (tmp == dist[e.to] && v < prevv[e.to])){
        dist[e.to] = tmp;
        prevv[e.to] = v;
        preve[e.to] = i;
        que.push(make_pair(-tmp, e.to));
      }
    }
  }
  // unfound
  return Path();
}

class PsuedoTree{
  struct node_t{
    int v;
    map<int, node_t*> ch;
    node_t(int s) : v(s) {}
    ~node_t(){
      for(map<int, node_t*>::iterator iter = ch.begin(); iter != ch.end(); iter++){
        delete iter->second;
      }
    }
  };
  
  node_t *root;
public:
  PsuedoTree(const Path &p){
    assert(!p.empty());
    root = new node_t(p.nodes[0]);
    add_path(p);
  }
  
  ~PsuedoTree(){ delete root; }
  
  void add_path(const Path &p){
    node_t *t = root;
    const vector<int> &nodes = p.nodes;
    assert(nodes[0] == t->v);
    
    vector<int> ignored_nodes;
    
    for(size_t i = 1; i < p.nodes.size(); i++){
      if(t->ch.find(nodes[i]) == t->ch.end()){
        t->ch[nodes[i]] = new node_t(nodes[i]);
      }
      t = t->ch[nodes[i]];
      
    }
  }
  
  void generate_candidate_path(const Graph &graph, int s, int t,
                               const Path &p,
                               priority_queue<Path> &path_que){
    int sum = 0;
    node_t *pt_node = root;
    vector<int> ignored_nodes;
    
    for(size_t i = 0; i + 1 < p.nodes.size(); i++){
      int v = p.nodes[i];
      vector<int> ignored_edges;
      
      for(size_t j = 0; j < graph[v].size(); j++){      
        if(pt_node->ch.find(graph[v][j].to) != pt_node->ch.end()){
          ignored_edges.push_back(j);
        }
      }
      
      ignored_nodes.push_back(v);
      Path candidate_path = dijkstra(graph, v, t, &ignored_nodes, &ignored_edges);
      if(!candidate_path.empty()){
        candidate_path = Path(sum, ignored_nodes) +  candidate_path;
        add_path(candidate_path);
        path_que.push(candidate_path);
      }
      
      pt_node = pt_node->ch[p.nodes[i+1]];
      assert(pt_node != NULL);
      
      for(size_t j = 0; j < graph[v].size(); j++)
        if(graph[v][j].to == p.nodes[i+1]) 
          sum += graph[v][j].cost;
    }
  }
};


vector<Path> topKShortestPath(const Graph &graph, int s, int t, int k){
  vector<Path> kshort(k);

  // cerr << "start computation" << endl;
  Path p = dijkstra(graph, s, t);
  if(p.empty()) return vector<Path>();
  
  PsuedoTree pt(p);
  priority_queue<Path> path_que;
  
  path_que.push(p);
  for(int i = 0; i < k; i++){
    if(path_que.empty()) return vector<Path>();

    kshort[i] = path_que.top(); path_que.pop();
    pt.generate_candidate_path(graph, s, t, kshort[i], path_que);
  }
  
  return kshort;
}
  

int main(){
  int n, m, k, a, b, x, y, d;
  while(cin >> n >> m >> k >> a >> b && (n + m + k + a + b) > 0){
    
    Graph g(n);
    for(int i = 0; i < m; i++){
      cin >> x >> y >> d;
      x--, y--;
      g[y].push_back(edge(x, d));
    }

    vector<Path> paths = topKShortestPath(g, --b, --a, k);
    if(paths.size() == 0){
      cout << "None" << endl;
    }else{
      paths[k-1].print();
    }
  }
  return 0;
}
```