Problem:
Problem E: Doragoso Ball
Problem
L
個集めるとドラゴソが現れどんな願いでも一つだけ叶えてくれるというドラゴソボールがとある迷宮に散らばっている。入口からスタートし、途中で立ち止まることなくすべてのボールを回収し、それらを迷宮内にある祭壇に奉納し、そのまま呪文を唱えるとドラゴソが現れ願いを叶えてくれるという。ただし、呪文を唱え始める時間は入口からボールを奉納するまでのルートのうち、移動時間が
K
番目に短いルートで移動したときの時間でなければならない。
この迷宮は部屋とわたり通路からなり、部屋と部屋はわたり通路を通る事によって行き来できる。ドラゴソボールはそれらの数ある部屋のどこかに落ちている。
なお、迷宮は入り口から祭壇へたどりつく道が存在しない可能性もあるようだ。また、移動時間はわたり通路の移動だけを考慮し、部屋の中を移動する時間、ボールを拾うときにかかる時間、祭壇に奉納する時間は考慮しなくてよい。
また、同じ通路や同じ部屋に何度も訪れてもよいが、ドラゴソボールがある部屋に初めて入った場合は、そのボールを拾うことにする。祭壇に到達したとき、必ずしもボールを納めなければならないわけではない。
迷宮の内部構造の情報と迷宮の入り口、祭壇の場所とボールの数
L
とボールの配置場所と求められている最短な経路の順位
K
が与えられるので、呪文を唱え始めるべき時間を求めよ。
また、異なる移動ルートでも、移動時間が同じである場合はそれらのルートは同じ順位として扱う。
例えば、
ルートA 時間 2
ルートB 時間 5
ルートC 時間 5
ルートD 時間 5
ルートE 時間 5
ルートF 時間 7
このようなとき、ルートB,C,D,Eは2位かつ3位かつ4位かつ5位として扱う。ルートFは6位として扱う。
Input
入力は複数のデータセットからなる。
各データセットは以下のフォーマットで表される。
N
M
L
K
u
1
v
1
c
1
…
u
M
v
M
c
M
S
G
B
1
B
2
…
B
L
最初に
N
,
M
,
L
,
K
が与えられる。
それぞれ、部屋の数、わたり通路の数、ボールの数、求められている最短な経路の順位を表す。それぞれの部屋は1〜
N
で番号付けされる。
次に
M
行にわたり通路の情報、
u
i
,
v
i
,
c
i
が与えられる。
部屋
u
i
,
v
i
間にわたり通路が存在し、通過するのに時間
c
i
がかかることを表す。
次に
S
,
G
が与えられる。
それぞれ、迷宮の入り口と祭壇がある部屋番号を表す。
次に
L
行にわたってドラゴソボールが落ちている部屋の番号
B
i
( 1 ≤
i
≤
L
)が与えられる。
入力の終わりは4つのゼロからなる。
Constraints
入力は以下の条件を満たす。
入力に含まれる値はすべて整数
2 ≤
N
≤ 50
0 ≤
M
≤ 1225
1 ≤
L
≤ 7
1 ≤
K
≤ 10
1 ≤
S
,
G
≤
N
1 ≤
B
i
≤
N
( 1 ≤
i
≤
L
)
B
i
≠
B
j
( 1 ≤
i
<
j
≤
L
)
1 ≤
u
i
,
v
i
≤
N
( 1 ≤
i
≤
M
)
1 ≤
c
i
≤ 1000 ( 1 ≤
i
≤
M
)
データセットは最大10個である
Output
各データセットに対し、呪文を唱え始めるべき時間を1行に出力せよ。
K
番目に短い経路が存在しない場合は"NA"を1行に出力せよ。
Sample Input
9 14 5 10
1 2 1
1 4 5
2 4 4
2 3 3
2 6 2
3 6 3
3 7 2
4 6 5
4 5 6
5 8 8
6 7 3
7 8 1
7 9 9
8 9 2
1 9
1
2
5
7
9
4 5 1 3
1 2 1
1 3 2
2 3 2
2 4 9
3 4 1
1 4
2
4 5 1 10
1 2 1
1 3 2
2 3 2
2 4 9
3 4 1
1 4
2
4 3 1 1
1 2 1
2 3 1
3 4 1
1 4
1
4 3 1 2
1 2 1
2 3 1
3 4 1
1 4
1
4 3 1 10
1 2 1
2 3 1
3 4 1
1 4
1
2 1 1 1
1 2 1
1 2
1
2 1 1 10
1 2 1
1 2
1
4 2 1 4
1 2 1
3 4 1
1 4
2
0 0 0 0
Sample Output
27
6
8
3
5
7
1
19
NA

Submitted solutions:

code_snippet: // AOJ #1513 Doragoso Ball
// 2025.2.20

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
 
struct Edge { int to, cost; };
 
struct State { ll cost; int room, mask; };
 
struct StateCompare {
    bool operator()(const State &a, const State &b) const {
        return a.cost > b.cost;
    }
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    while(true){
        int N, M, L, K;
        cin >> N >> M >> L >> K;
        if(N==0) break;
 
        vector<vector<Edge>> graph(N+1);
        for (int i=0; i<M; i++){
            int u, v, c;
            cin >> u >> v >> c;
            graph[u].push_back({v,c});
            graph[v].push_back({u,c});
        }
 
        int S, G;
        cin >> S >> G;
 
        vector<int> ballIndex(N+1, -1);
        vector<int> ballRooms(L);
        for (int i=0; i<L; i++){
            int b;
            cin >> b;
            ballRooms[i] = b;
            ballIndex[b] = i;
        }
 
        int initMask = 0;
        if(ballIndex[S] != -1) initMask |= (1 << ballIndex[S]);
 
        int fullMask = (1 << L) - 1;
 
        vector<vector<int>> cnt(N+1, vector<int>(1 << L, 0));
 
        priority_queue<State, vector<State>, StateCompare> pq;
        pq.push({0, S, initMask});
 
        int found = 0;
        ll ans = -1;
        while(!pq.empty()){
            State cur = pq.top();
            pq.pop();
 
            if(cnt[cur.room][cur.mask] >= K) continue;
            cnt[cur.room][cur.mask]++;
 
            if(cur.room == G && cur.mask == fullMask){
                found++;
                if(found == K){
                    ans = cur.cost;
                    break;
                }
            }
 
            for(auto &edge : graph[cur.room]){
                int nxt = edge.to;
                ll ncost = cur.cost + edge.cost;
                int nmask = cur.mask;
                if(ballIndex[nxt] != -1) nmask |= (1 << ballIndex[nxt]);
                pq.push({ncost, nxt, nmask});
            }
        }
        if(ans < 0) cout << "NA" << endl;
        else cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 820
memory_kb: 70920
final_rank: 14

code_snippet: #include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;

int N;
int M, U[1250], V[1250], C[1250];
int L;
int K;
int Start, Goal;
int B[69];
int mask[69];

// Graph
pair<int, int> Dist[59][1 << 7][21];
vector<pair<int, int>> G[59];
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> Q;

void Initialize() {
	for (int i = 0; i < 59; i++) G[i].clear();
	for (int i = 0; i < 59; i++) B[i] = 0;
	for (int i = 0; i < 59; i++) mask[i] = 0;
	for (int i = 0; i < 59; i++) {
		for (int j = 0; j < 128; j++) {
			for (int k = 0; k < 21; k++) Dist[i][j][k] = make_pair(0, 0);
		}
	}
}

int main() {
	while (true) {
		Initialize();

		// Step 1. Input
		cin >> N >> M >> L >> K; if (N + M + L + K == 0) break;
		for (int i = 0; i < M; i++) cin >> U[i] >> V[i] >> C[i];
		cin >> Start >> Goal;
		for (int i = 0; i < L; i++) cin >> B[i];

		// Step 2. Initialize
		for (int i = 1; i <= N; i++) mask[i] = 0;
		for (int i = 0; i < L; i++) mask[B[i]] = (1 << i);
		for (int i = 0; i < M; i++) {
			G[U[i]].push_back(make_pair(V[i], C[i]));
			G[V[i]].push_back(make_pair(U[i], C[i]));
		}

		// Step 3. Dijkstra Init
		for (int i = 1; i <= N; i++) {
			for (int j = 0; j < (1 << 7); j++) {
				for (int k = 0; k < 10; k++) Dist[i][j][k] = make_pair(100000000, k);
			}
		}
		Dist[Start][mask[Start]][0] = make_pair(0, Start);
		Q.push(make_tuple(0, Start, mask[Start]));

		// Step 4. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			Q.pop();
			for (pair<int, int> tmp : G[pos1]) {
				int nex1 = tmp.first;
				int nex2 = (pos2 | mask[nex1]);

				// Calculate Cost
				vector<pair<int, int>> vec;
				for (int i = 0; i < K; i++) vec.push_back(Dist[nex1][nex2][i]);
				for (int i = 0; i < K; i++) {
					if (Dist[pos1][pos2][i].first == 100000000) continue;
					int cost_ = Dist[pos1][pos2][i].first + tmp.second;
					int hash_ = Dist[pos1][pos2][i].second * 233 + nex1;
					vec.push_back(make_pair(cost_, hash_));
				}
				sort(vec.begin(), vec.end());
				vec.erase(unique(vec.begin(), vec.end()), vec.end());

				// Check Difference
				int MinDiff = (1 << 30);

				for (int i = 0; i < K; i++) {
					if (Dist[nex1][nex2][i].first == vec[i].first) continue;
					MinDiff = min(MinDiff, vec[i].first);
				}
				for (int i = 0; i < K; i++) Dist[nex1][nex2][i] = vec[i];
				if (MinDiff != (1 << 30)) Q.push(make_tuple(MinDiff, nex1, nex2));
			}
		}

		// Step 5. Final
		if (Dist[Goal][(1 << L) - 1][K - 1].first == 100000000) cout << "NA" << endl;
		else cout << Dist[Goal][(1 << L) - 1][K - 1].first << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 2180
memory_kb: 4852
final_rank: 10

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;


struct Info{
	Info(int arg_to,int arg_cost){
		to = arg_to;
		cost = arg_cost;
	}
	int to,cost;
};

struct Data{
	Data(int arg_node_id,int arg_ball_state,int arg_total_cost){
		node_id = arg_node_id;
		ball_state = arg_ball_state;
		total_cost = arg_total_cost;
	}
	bool operator<(const struct Data &arg) const{
		return total_cost > arg.total_cost;
	}
	int node_id,ball_state,total_cost;
};

int N,M,L,K;
int POW[8],min_cost[50][10][128],index[50][128],exist_ball[50];
vector<Info> G[50];


void func(){

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

	int from,to,cost;
	for(int i = 0; i < M; i++){
		scanf("%d %d %d",&from,&to,&cost);
		from--;
		to--;
		G[from].push_back(Info(to,cost));
		G[to].push_back(Info(from,cost));
	}

	int start,goal;
	scanf("%d %d",&start,&goal);
	start--;
	goal--;

	for(int i = 0; i < N; i++)exist_ball[i] = -1;

	int tmp;
	for(int i = 0; i < L; i++){
		scanf("%d",&tmp);
		tmp--;
		exist_ball[tmp] = i;
	}

	for(int i = 0; i < N; i++){
		for(int state = 0; state < POW[L]; state++)index[i][state] = 0;
	}

	for(int i = 0; i < N; i++){
		for(int a = 0; a < K; a++){
			for(int state = 0; state < POW[L]; state++)min_cost[i][a][state] = BIG_NUM;
		}
	}

	priority_queue<Data> Q;

	int first_state;

	if(exist_ball[start] != -1){
		first_state = POW[exist_ball[start]];
	}else{
		first_state = 0;
	}
	min_cost[start][index[start][first_state]++][first_state] = 0;

	int next_node,next_state;

	for(int i = 0; i < G[start].size(); i++){
		next_node = G[start][i].to;

		if(exist_ball[next_node] != -1){
			next_state = first_state|POW[exist_ball[next_node]];
		}else{
			next_state = first_state;
		}
		if(index[next_node][next_state] >= K)continue;

		Q.push(Data(next_node,next_state,G[start][i].cost));
	}


	while(!Q.empty()){

		if(index[Q.top().node_id][Q.top().ball_state] >= K){
			if(Q.top().node_id == goal && Q.top().ball_state == POW[L]-1)break;
			Q.pop();
			continue;
		}

		min_cost[Q.top().node_id][index[Q.top().node_id][Q.top().ball_state]++][Q.top().ball_state] = Q.top().total_cost;

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

			if(exist_ball[next_node] != -1){
				next_state = Q.top().ball_state|POW[exist_ball[next_node]];
			}else{
				next_state = Q.top().ball_state;
			}

			if(index[next_node][next_state] >= K)continue;

			Q.push(Data(next_node,next_state,Q.top().total_cost+G[Q.top().node_id][i].cost));
		}
		Q.pop();
	}

	if(min_cost[goal][K-1][POW[L]-1] == BIG_NUM){
		printf("NA\n");
	}else{
		printf("%d\n",min_cost[goal][K-1][POW[L]-1]);
	}
}


int main(){

	for(int i = 0; i < 8; i++)POW[i] = pow(2,i);

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 670
memory_kb: 41112
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;


struct Info{
	Info(int arg_to,int arg_cost){
		to = arg_to;
		cost = arg_cost;
	}
	int to,cost;
};

struct Data{
	Data(int arg_node_id,int arg_ball_state,int arg_total_cost){
		node_id = arg_node_id;
		ball_state = arg_ball_state;
		total_cost = arg_total_cost;
	}
	bool operator<(const struct Data &arg) const{
		return total_cost > arg.total_cost;
	}
	int node_id,ball_state,total_cost;
};

int N,M,L,K;
int POW[8],min_cost[50][10][128],index[50][128],exist_ball[50];
vector<Info> G[50];


void func(){

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

	int from,to,cost;
	for(int i = 0; i < M; i++){
		scanf("%d %d %d",&from,&to,&cost);
		from--;
		to--;
		G[from].push_back(Info(to,cost));
		G[to].push_back(Info(from,cost));
	}

	int start,goal;
	scanf("%d %d",&start,&goal);
	start--;
	goal--;

	for(int i = 0; i < N; i++)exist_ball[i] = -1;

	int tmp;
	for(int i = 0; i < L; i++){
		scanf("%d",&tmp);
		tmp--;
		exist_ball[tmp] = i;
	}

	for(int i = 0; i < N; i++){
		for(int state = 0; state < POW[L]; state++)index[i][state] = 0;
	}

	for(int i = 0; i < N; i++){
		for(int a = 0; a < K; a++){
			for(int state = 0; state < POW[L]; state++)min_cost[i][a][state] = BIG_NUM;
		}
	}

	priority_queue<Data> Q;

	int first_state;

	if(exist_ball[start] != -1){
		first_state = POW[exist_ball[start]];
	}else{
		first_state = 0;
	}
	min_cost[start][index[start][first_state]++][first_state] = 0;

	int next_node,next_state;

	for(int i = 0; i < G[start].size(); i++){
		next_node = G[start][i].to;

		if(exist_ball[next_node] != -1){
			next_state = first_state|POW[exist_ball[next_node]];
		}else{
			next_state = first_state;
		}
		if(index[next_node][next_state] >= K)continue;

		Q.push(Data(next_node,next_state,G[start][i].cost));
	}


	while(!Q.empty()){

		if(index[Q.top().node_id][Q.top().ball_state] >= K){
			Q.pop();
			continue;
		}

		min_cost[Q.top().node_id][index[Q.top().node_id][Q.top().ball_state]++][Q.top().ball_state] = Q.top().total_cost;

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

			if(exist_ball[next_node] != -1){
				next_state = Q.top().ball_state|POW[exist_ball[next_node]];
			}else{
				next_state = Q.top().ball_state;
			}

			if(index[next_node][next_state] >= K)continue;

			Q.push(Data(next_node,next_state,Q.top().total_cost+G[Q.top().node_id][i].cost));
		}
		Q.pop();
	}

	if(min_cost[goal][K-1][POW[L]-1] == BIG_NUM){
		printf("NA\n");
	}else{
		printf("%d\n",min_cost[goal][K-1][POW[L]-1]);
	}
}


int main(){

	for(int i = 0; i < 8; i++)POW[i] = pow(2,i);

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

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 1520
memory_kb: 41160
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define pb push_back 
#define fr first
#define sc second
#define Rep(i,n) for(int i=0;i<(n);i++)
#define All(v) v.begin(),v.end()
#define Uniq(v) v.erase(unique(All(v)),v.end())
typedef pair<int, int> Pii; 
typedef pair<int, Pii> Pip;
typedef pair<string, int> Psi;
const int INF = (1<<30);
const int dx[]={1,0,-1,0}, dy[]={0,-1,0,1};

struct Edge {
  int to, cost;
  Edge(int to_, int cost_) {
    to = to_; cost = cost_;
  }
};

struct State {
  int room, cost, bit;
  State(int room_, int cost_, int bit_) {
    room = room_; cost = cost_; bit = bit_;
  }
  bool operator<(const State& s) const {
    return cost < s.cost;
  }
  bool operator>(const State& s) const {
    return cost > s.cost;
  }
};

int N, M, L, K;
int S, G;
int ball_room[8];
vector<Edge> graph[51];

int dij()
{
  priority_queue<State, vector<State>, greater<State> > q;
  int used[51][1 << 8] = {{0}};
  int cnt = 0; //これがKになったらコストを返す

  Rep(i, L) {
    if( ball_room[i] == S ) {
      q.push( State(S, 0, 1 << i) );
      break;
    }
    if( i == L-1 ) q.push( State(S, 0, 0) );
  }

  while( !q.empty() ) {
    State p = q.top(); q.pop();
    int room = p.room, cost = p.cost, bit = p.bit;
    if( room == G && bit == (1 << L)-1 ) {
      cnt++;
      if( cnt == K ) return cost;
    }
  
    if( used[room][bit] >= K ) continue;
    used[room][bit]++;

    vector<Edge> e = graph[room];
    Rep(i, e.size()) {
      int next = e[i].to, next_bit = bit, next_cost = cost + e[i].cost;
      Rep(j, L) {
	if( ball_room[j] == next ) {
	  next_bit = (next_bit | (1 << j)); 
	  break;
	}
      }
      if( used[next][next_bit] >= K ) continue;
      q.push( State(next, next_cost, next_bit) );
    }
  }

  return -1;
}



int main()
{
  while( cin >> N >> M >> L >> K, N ) {
    Rep(i, 51) graph[i].clear();
    Rep(i, M) {
      int a, b, c;
      cin >> a >> b >> c;
      a--; b--;
      graph[a].pb( Edge(b, c) );
      graph[b].pb( Edge(a, c) );
    }
    
    cin >> S >> G;
    S--; G--;
    
    Rep(i, L) {
      cin >> ball_room[i];
      ball_room[i]--;
    }
    
    int ans = dij();
    if( ans == -1 ) cout << "NA" << endl;
    else cout << ans << endl;
  }
}
accuracy: 1
time_ms: 660
memory_kb: 40648
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define pb push_back 
#define fr first
#define sc second
#define Rep(i,n) for(int i=0;i<(n);i++)
#define All(v) v.begin(),v.end()
#define Uniq(v) v.erase(unique(All(v)),v.end())
typedef pair<int, int> Pii; 
typedef pair<int, Pii> Pip;
typedef pair<string, int> Psi;
const int INF = (1<<30);
const int dx[]={1,0,-1,0}, dy[]={0,-1,0,1};

struct Edge {
  int to, cost;
  Edge(int to_, int cost_) {
    to = to_; cost = cost_;
  }
};

struct State {
  int room, cost, bit;
  State(int room_, int cost_, int bit_) {
    room = room_; cost = cost_; bit = bit_;
  }
  bool operator<(const State& s) const {
    return cost < s.cost;
  }
  bool operator>(const State& s) const {
    return cost > s.cost;
  }
};

int N, M, L, K;
int S, G;
int ball_room[8];
vector<Edge> graph[51];

int dij()
{
  priority_queue<State, vector<State>, greater<State> > q;
  int used[51][1 << 8] = {{0}};
  int cnt = 0; //これがKになったらコストを返す

  Rep(i, L) {
    if( ball_room[i] == S ) {
      q.push( State(S, 0, 1 << i) );
      break;
    }
    if( i == L-1 ) q.push( State(S, 0, 0) );
  }

  while( !q.empty() ) {
    State p = q.top(); q.pop();
    int room = p.room, cost = p.cost, bit = p.bit;
    if( room == G && bit == (1 << L)-1 ) {
      cnt++;
      if( cnt == K ) return cost;
    }
  
    if( used[room][bit] > K ) continue;
    used[room][bit]++;

    vector<Edge> e = graph[room];
    Rep(i, e.size()) {
      int next = e[i].to, next_bit = bit, next_cost = cost + e[i].cost;
      Rep(j, L) {
	if( ball_room[j] == next ) {
	  next_bit = (next_bit | (1 << j)); 
	  break;
	}
      }
      if( used[next][next_bit] > K ) continue;
      q.push( State(next, next_cost, next_bit) );
    }
  }

  return -1;
}



int main()
{
  while( cin >> N >> M >> L >> K, N ) {
    Rep(i, 51) graph[i].clear();
    Rep(i, M) {
      int a, b, c;
      cin >> a >> b >> c;
      a--; b--;
      graph[a].pb( Edge(b, c) );
      graph[b].pb( Edge(a, c) );
    }
    
    cin >> S >> G;
    S--; G--;
    
    Rep(i, L) {
      cin >> ball_room[i];
      ball_room[i]--;
    }
    
    int ans = dij();
    if( ans == -1 ) cout << "NA" << endl;
    else cout << ans << endl;
  }
}
accuracy: 1
time_ms: 820
memory_kb: 43268
final_rank: 11

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

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef complex<double> P;
typedef pair<int,int> pii;
#define REP(i,n) for(ll i=0;i<n;++i)
#define REPR(i,n) for(ll i=1;i<n;++i)
#define FOR(i,a,b) for(ll i=a;i<b;++i)

#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define DEBUG_VEC(v) cout<<#v<<":";REP(i,v.size())cout<<" "<<v[i];cout<<endl
#define ALL(a) (a).begin(),(a).end()

#define MOD (ll)(1e9+7)
#define ADD(a,b) a=((a)+(b))%MOD
#define FIX(a) ((a)%MOD+MOD)%MOD

struct edge{
  int src,dst,cost;
  edge(int s,int d,int c):src(s),dst(d),cost(c){}
};

struct state{
  int pos,dist,balls;
  state(int p,int d,int b):pos(p),dist(d),balls(b){}
};
bool operator<(const state &a,const state &b){
  if(a.dist!=b.dist)return a.dist>b.dist;
  return a.pos<b.pos;
}

// [at][balls]
int times[50][1<<7];
// ??¶?????°??????????????? N * 2^L * K

bool solve(){
  int n,m,l,k;
  cin>>n>>m>>l>>k;
  if(!n)return false;
  assert(n<=50);
  assert(m<=1225);
  assert(l<=7);
  assert(k<=10);
  vector<edge> edges[n];
  REP(i,m){
    int u,v,c;
    cin>>u>>v>>c;
    --u; --v;
    edges[u].push_back(edge(u,v,c));
    edges[v].push_back(edge(v,u,c));
  }
  int start,goal;
  cin>>start>>goal;
  --start; --goal;
  int ball[n]; REP(i,n)ball[i]=0;
  REP(i,l){
    int b;
    cin>>b;
    ball[b-1] = 1<<i;
  }
  int maxball = (1<<l)-1;
  REP(i,n)REP(j,1<<l){
    times[i][j]=0;
  }
  priority_queue<state> Q;
  Q.push(state(start,0,0|ball[start]));
  int result = -1;
  while(!Q.empty()){
    state S = Q.top(); Q.pop();
    if(times[S.pos][S.balls] >= k)continue;
    times[S.pos][S.balls] ++;
    if(S.pos==goal && S.balls==maxball && times[S.pos][S.balls]==k){
      result = S.dist;
      break;
    }
    REP(i,edges[S.pos].size()){
      edge E = edges[S.pos][i];
      Q.push(state(E.dst,S.dist+E.cost,S.balls|ball[E.dst]));
    }
  }
  if(result==-1){
    cout<<"NA"<<endl;
  }else{
    cout<<result<<endl;
  }
  return true;
}

int main(){
  while(solve());
  return 0;
}
accuracy: 1
time_ms: 1380
memory_kb: 76940
final_rank: 17

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_N = 50;
const int MAX_M = 1225;
const int MAX_K = 10;
const int MAX_L = 7;
const int MAX_BITS = (1 << MAX_L);

const int INF = 1 << 30;

/* typedef */

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

struct Stat {
  int i, b, d;
  Stat(int _i, int _b, int _d) { i = _i, b = _b, d = _d; }
  bool operator<(const Stat& s) const { return d > s.d; }
};

/* global variables */

int n, m, l, k;
int st, gl, gbits;
int bis[MAX_N];

vpii nbrs[MAX_N];
int dists[MAX_N][MAX_BITS][MAX_K];

/* main */

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

    gbits = (1 << l) - 1;

    for (int i = 0; i < n; i++) {
      nbrs[i].clear();
      bis[i] = -1;
      for (int b = 0; b <= gbits; b++)
	for (int j = 0; j < k; j++) dists[i][b][j] = INF;
    }

    for (int i = 0; i < m; i++) {
      int u, v, c;
      cin >> u >> v >> c;
      u--, v--;
      nbrs[u].push_back(pii(v, c));
      nbrs[v].push_back(pii(u, c));
    }

    cin >> st >> gl;
    st--, gl--;

    for (int i = 0; i < l; i++) {
      int bi;
      cin >> bi;
      bi--;
      bis[bi] = i;
    }

    int sb = (bis[st] >= 0) ? (1 << bis[st]) : 0;
    
    priority_queue<Stat> q;
    q.push(Stat(st, sb, 0));
    dists[st][sb][0] = 0;
    
    int distk = -1;
    
    while (! q.empty()) {
      Stat u = q.top();
      q.pop();

      int udk = dists[u.i][u.b][k - 1];
      if (u.d > udk) continue;
      
      if (u.i == gl && u.b == gbits && u.d == udk) {
	distk = u.d;
	break;
      }

      vpii& nbru = nbrs[u.i];
      for (vpii::iterator vit = nbru.begin(); vit != nbru.end(); vit++) {
	int vi = vit->first;

	int vb = u.b;
	if (bis[vi] >= 0) vb |= (1 << bis[vi]);

	int vd = u.d + vit->second;
	int *dpt = dists[vi][vb];
	
	if (dpt[k - 1] > vd) {
	  dpt[k - 1] = vd;
	  for (int ki = k - 1; ki > 0 && dpt[ki] < dpt[ki - 1]; ki--) {
	    int tmp = dpt[ki]; dpt[ki] = dpt[ki - 1]; dpt[ki - 1] = tmp;
	  }
	  q.push(Stat(vi, vb, vd));
	}
      }
    }

    if (distk < 0)
      cout << "NA" << endl;
    else
      cout << distk << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 4244
final_rank: 1

code_snippet: #include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
//#include <utility>
#include <set>
#include <iostream>
//#include <memory>
#include <string>
#include <vector>
#include <algorithm>
//#include <functional>
#include <sstream>
//#include <deque>
#include <complex>
#include <stack>
#include <queue>
#include <cstdio>
//#include <cctype>
#include <cstring>
//#include <ctime>
#include <iterator>
#include <bitset>
//#include <numeric>
//#include <list>
//#include <iomanip>

#if __cplusplus >= 201103L
#include <array>
#include <tuple>
#include <initializer_list>
#include <unordered_set>
#include <unordered_map>
#include <forward_list>

#define cauto const auto&
#else

#endif

using namespace std;


namespace{
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;
typedef pair<pii,int> P;

#define VV(T) vector<vector< T > >

template <class T>
void initvv(vector<vector<T> > &v, int a, int b, const T &t = T()){
    v.assign(a, vector<T>(b, t));
}

template <class F, class T>
void convert(const F &f, T &t){
    stringstream ss;
    ss << f;
    ss >> t;
}


#define reep(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n) reep((i),0,(n))
#define ALL(v) (v).begin(),(v).end()
#define PB push_back
#define F first
#define S second
#define mkp make_pair
#define RALL(v) (v).rbegin(),(v).rend()


#define MOD 1000000007LL
#define EPS 1e-8
static const int INF=1<<24;
/*
10^3*50*100*
*/
int vis[55][11][(1<<7)+10];
void mainmain(){
	int n,m,L,K;
	while(cin>>n>>m>>L>>K,n){
		vint ball(n,-1);
		VV(pii) vv(n);
		rep(i,m){
			int a,b,c;
			cin>>a>>b>>c;
			vv[a-1].PB(mkp(b-1,c));
			vv[b-1].PB(mkp(a-1,c));
		}
		int s,g;
		cin>>s>>g;
		s--;
		g--;
		int cnt=0;
		rep(i,L){
			int t;
			cin>>t;
			ball[t-1]=cnt++;
		}
		rep(i,55){
			rep(j,11){
				rep(k,(1<<7)+10){
					vis[i][j][k]=INF;
				}
			}
		}
		priority_queue<P> pq;
		pq.push(mkp(mkp(0,0),s));
		while(!pq.empty()){
			P top=pq.top();
			pq.pop();
			top.F.S*=-1;
			// cout<<-top.F.F<<" "<<top.F.S<<" "<<top.S+1<<endl;
			if(ball[top.S]!=-1) top.F.S|=1<<ball[top.S];
			bool f=false;
			int t=-top.F.F;
			rep(i,K){
				if(t<vis[top.S][i][top.F.S]){
					// cout<<"t "<<t<<endl;
					swap(vis[top.S][i][top.F.S],t);
					f=true;
				}
			}
			if(!f) continue;
			rep(i,vv[top.S].size()){
				P tmp=top;
				if(ball[vv[top.S][i].F]!=-1) tmp.F.S|=1<<ball[vv[top.S][i].F];
				if(vis[vv[top.S][i].F][K-1][tmp.F.S]<vv[top.S][i].S-tmp.F.F) continue;
				tmp.F.S*=-1;
				tmp.F.F-=vv[top.S][i].S;
				tmp.S=vv[top.S][i].F;
				pq.push(tmp);
			}
		}
		if(vis[g][K-1][(1<<L)-1]!=INF) cout<<vis[g][K-1][(1<<L)-1]<<endl;
		else cout<<"NA"<<endl;
	}
}



}
main() try{
    mainmain();
}
catch(...){
}
accuracy: 1
time_ms: 1920
memory_kb: 40084
final_rank: 13

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

#define REP(i,n) for(int i=0;i<(int)(n);i++)

using namespace std;

typedef int Weight;
Weight INF = 1000000000;
struct Edge{
  int src, dest; Weight weight;
  bool operator < (const Edge &rhs) const {return weight > rhs.weight;}
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, Weight weight) {
  g[src].push_back((Edge){src, dest, weight});
}

// Dijkstra (Verified: AOJ2005)
void dijkstra(Graph &g, Matrix &d, int s) {
  REP(i,g.size()) d[i].assign(10, INF);
  d[s][0] = 0;
  typedef pair<Weight,int> P;
  priority_queue<P, vector<P>, greater<P> > que;
  que.push(P(0, s));
  while (!que.empty()) {
    Weight dist = que.top().first;
    int v = que.top().second;
    que.pop();
    auto itr=find(begin(d[v]),end(d[v]),dist);
    if (itr == end(d[v])) continue;
    REP(i, g[v].size()) {
      Edge e = g[v][i];
      REP(j,10) {
        if (d[e.dest][j] > dist + e.weight) {
          d[e.dest].insert(begin(d[e.dest])+j, dist + e.weight);
          d[e.dest].pop_back();
          que.push(P(d[e.dest][j], e.dest));
          break;
        }
      }
    }
  }
}

int main() {
  while(1){
    int n,m,l,k;
    cin>>n>>m>>l>>k;
    if(!n)break;
    --k;
    int z=1<<l;
    Graph g(n*z);
    vector<tuple<int,int,int>> es;
    REP(i,m){
      int u,v,c;
      cin>>u>>v>>c;
      --u;--v;
      es.emplace_back(u,v,c);
    }
    int s,t;
    cin>>s>>t;
    --s;--t;
    vector<int> db(l);
    REP(i,l)cin>>db[i];
    REP(i,l)--db[i];
    REP(i,m) {
      int u,v,c;
      tie(u,v,c)=es[i];
      REP(j,z){
        bitset<7> bs(j);
        bool tku = false;
        bool tkv = false;
        REP(p,l){
          if (!bs[p]) {
            if (db[p]==u) {
              add_edge(g,v*z+j,u*z+j+(1<<p),c);
              tku = true;
            }
            if(db[p]==v) {
              add_edge(g,u*z+j,v*z+j+(1<<p),c);
              tkv = true;
            }
          }
        }
        if(!tku) add_edge(g,v*z+j,u*z+j,c);
        if(!tkv) add_edge(g,u*z+j,v*z+j,c);
      }
    }
    Matrix dist(n*z);
    REP(i,dist.size()) dist[i]=Array(10);
    auto itr = find(begin(db),end(db),s);
    if (itr == end(db))
      dijkstra(g,dist,s*z);
    else
      dijkstra(g,dist,s*z+(1<<(itr-begin(db))));
    int ti=t*z+z-1;
    if(dist[ti][k] < INF)
      cout<<dist[ti][k]<<endl;
    else
      cout<<"NA"<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 8620
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)
using namespace std;
typedef long long LL;
struct Edge{
    int dst, cost;
};
typedef vector<Edge> Node;
typedef vector<Node> Graph;
typedef tuple<int, int, int> P;

int mask(int cur, vector<int> B) {
    int s = 0;
    REP(i, B.size()) if(B[i] == cur + 1) s |= (1 << i);
    return s;
}

int main(){
    int N, M, L, K;
    while(cin >> N >> M >> L >> K && N > 0) {
        Graph G(N);

        REP(i, M) {
            int u, v, c;
            cin >> u >> v >> c;
            u--; v--;
            G[u].push_back({v, c});
            G[v].push_back({u, c});
        }

        int start, goal;
        cin >> start >> goal;
        start--; goal--;

        vector<int> B(L);
        REP(i, L) cin >> B[i];

        vector<int> dist[55][1 << 8];
        priority_queue<P, vector<P>, greater<P>> que;
        que.push(P(0, start, mask(start, B)));
        while(!que.empty()) {
            auto p = que.top(); que.pop();
            int d, u, s;
            tie(d, u, s) = p;
            if(dist[u][s].size() >= K) continue;
            dist[u][s].push_back(d);
            for(auto e : G[u]) {
                int nu = e.dst;
                int nd = d + e.cost;
                int ns = s | mask(nu, B);
                if(dist[nu][ns].size() < K)  {
                    que.push(P(nd, nu, ns));
                }
            }
        }
        if(dist[goal][(1 << L) - 1].size() == K) {
            cout << dist[goal][(1 << L) - 1][K-1] << endl;
        } else {
            assert(dist[goal][(1 << L) - 1].size() == 0);
            cout << "NA" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 2410
memory_kb: 41304
final_rank: 16

code_snippet: #include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
typedef pair<int, int> P;
const int MAX_V = 51;
const int MAX_L = (1 << 10);
const int MAX_K = 15;
const int INF = 1e9;
#define DEBUG

class C{
  public:
    int n, t, b;
    C(){}
    C( int _n, int _t ){ n = _n; t = _t; b = 0; }
    C( int _n, int _t, int _b){ n = _n; t = _t; b = _b; }
    bool operator > (const C &c) const { return t > c.t; }
};

int G[MAX_V][MAX_V], S, T, V, E, L, K;
bool B[MAX_V];
int closed[MAX_V][MAX_L][MAX_K], cnt[MAX_V][MAX_L];;
map<int, int> bn;

int solve(){
  priority_queue<C, vector<C>, greater<C>> open;
  open.push(C(S, 0));
  REP(i, MAX_V) REP(j, MAX_L) REP(k, MAX_K) closed[i][j][k] = INF;
  REP(i, MAX_V) REP(j, MAX_L) cnt[i][j] = 0;
  while(!open.empty()){
    C now = open.top(); open.pop();
    int n = now.n, b = now.b, t = now.t;
    if(B[n]) b = (b | (1 << bn[n]));
    if(cnt[n][b] >= K || closed[n][b][cnt[n][b]] < t) continue;
    closed[n][b][cnt[n][b]++] = t;
    REP(next, V){
      if(G[n][next] == INF) continue;
      open.push(C(next, t + G[n][next], b));
    }
  }
  return (closed[T][(1 << L) - 1][K - 1] == INF ? -1 : closed[T][(1 << L) - 1][K - 1]);
}

int main() {
  while(cin >>V >>E >>L >>K && V){
    REP(i, MAX_V) REP(j, MAX_V) G[i][j] = INF;
    memset(B, 0, sizeof(B));
    REP(i, E){
      int u, v, c; cin >>u >>v >>c;
      --u; --v;
      G[u][v] = G[v][u] = c;
    }
    cin >>S >>T;
    --S; --T;
    REP(i, L){
      int n; cin >>n;
      --n;
      B[n] = true;
      bn[n] = i;
    }
    int ans = solve();
    if(ans == -1) cout <<"NA" <<endl;
    else cout <<ans <<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 2680
memory_kb: 79408
final_rank: 19

code_snippet: #include <string> 
#include <algorithm> 
#include <cfloat> 
#include <climits> 
#include <cmath> 
#include <complex> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <functional> 
#include <iostream> 
#include <map> 
#include <memory> 
#include <queue> 
#include <set> 
#include <sstream> 
#include <stack> 
#include <utility> 
#include <vector> 

#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define ALL(x) (x).begin(),(x).end() 
using namespace std; 
typedef long long ll;
const double eps = 1e-10;

typedef int Weight;
const Weight INF = 100000000;
struct Edge{
    int from, to;
    Weight weight;
    int rev;     // ネットワークフロー時の逆辺
    Edge(int from, int to, Weight weight) :
        from(from), to(to), weight(weight) { }
    Edge(int from, int to, Weight weight, int rev) :
        from(from), to(to), weight(weight), rev(rev){ }
};
bool operator < (const Edge &a, const Edge &b){
    if(a.weight != b.weight) return a.weight > b.weight;
    if(a.from != b.from) return a.from > b.from;
    return  a.to > b.to;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void addFlowEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, 0, g[a].size() - 1));
}
void addUndirectedEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, c, g[a].size() - 1));
}

int N, M, L, K;
int S, G;
int B[10];
int ball[60];
int dist[60][1<<7][10];

void dijkstra(const Graph &g, int s){
    int n = g.size();
    priority_queue<pair<Edge, int> > Q; // a < b <-> a.weight > b.weight
    for(int i = 1; i <= N; ++i)for(int j = 0; j < 1 << L; ++j)
        for(int k = 0; k < K; ++k) dist[i][j][k] = INF;

    int bb = ball[s] >= 0 ? 1 << ball[s]: 0;
    Q.push(make_pair(Edge(-2, s, 0), bb));
    dist[S][bb][0] = 0;
    while(!Q.empty()){
        Edge e = Q.top().first;
        int bit = Q.top().second;
        Q.pop();
        EACH(i, g[e.to]){
            int nb = bit, nw = i->weight+e.weight;
            if(ball[i->to] >= 0) nb |= 1 << ball[i->to];
            if(dist[i->to][nb][K-1] > nw){
                dist[i->to][nb][K-1] = nw;
                for(int j = K-1; j > 0; --j) if(dist[i->to][nb][j] < dist[i->to][nb][j-1])
                    swap(dist[i->to][nb][j], dist[i->to][nb][j-1]);
                Q.push(make_pair(Edge(i->from, i->to, nw), nb));
            }
        }
    }
}

int main(){
    for(;;){
        cin >> N >> M >> L >> K;
        if(N==0) return 0;
        Graph g(N+1);
        for(int i = 0; i < M; ++i){
            int a, b, c;
            cin >> a >> b >> c;
            addUndirectedEdge(g, a, b, c);
        }
        cin >> S >> G;
        for(int i = 0; i < L; ++i) cin >> B[i];
        sort(B, B+L);
        memset(ball, -1, sizeof(ball));
        for(int i = 0; i < L; ++i) ball[B[i]] = i;
        dijkstra(g, S);
        if(dist[G][(1<<L)-1][K-1] == INF) cout << "NA" << endl;
        else                    cout << dist[G][(1<<L)-1][K-1] << endl;
    }
}
accuracy: 1
time_ms: 490
memory_kb: 6388
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <iterator>
#include <bitset>
#include <random>
#include <assert.h>
#include <unordered_map>
#include <array>
#include <ctime>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second
#define MP make_pair
#define umap unordered_map

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> P;
typedef unsigned int uint;

const int N = 55;

int d[N][N];
vector<P> G[N];
int ball[N];

priority_queue<int> cand[N][1 << 7];

struct state{
	int pos, visit, total;
	bool operator < (const state &r) const{
		return total > r.total;
	}
};

int main(){
	ios::sync_with_stdio(false);

	int n, m, l, k;
	while (cin >> n >> m >> l >> k, n | m | l | k){
		rep(i, N) rep(j, N) d[i][j] = 1 << 29;
		rep(i, N) rep(j, 1 << 7) while (!cand[i][j].empty()) cand[i][j].pop();
		rep(i, N) G[i].clear();
		MEMSET(ball, 0);
		rep(i, m){
			int u, v, c;
			cin >> u >> v >> c;
			--u, --v;
			d[u][v] = d[v][u] = c;
			G[u].push_back(MP(v, c));
			G[v].push_back(MP(u, c));
		}
		int s, g;
		cin >> s >> g;
		--s, --g;
		rep(i, l){
			int b;
			cin >> b;
			ball[--b] = 1 << i;
		}
		rep(i, n) rep(j, n) rep(k, n) d[j][k] = min(d[j][k], d[j][i] + d[i][k]);

		priority_queue<state> q;
		q.push({s, ball[s], 0});

		int cnt = 0, ans = -1;
		if (d[s][g] >= 1 << 29) goto fail;
		while (!q.empty()) {
			auto s = q.top();
			q.pop();

			auto &pq = cand[s.pos][s.visit];
			if (!pq.empty() && pq.top() < s.total) continue;

			if (s.pos == g && s.visit + 1 == (1 << l)){
				//cout << s.total << endl;
				if (++cnt == k){
					ans = s.total;
					break;
				}
			}

			for (auto e : G[s.pos]){
				state nxt = s;
				nxt.pos = e.first;
				nxt.total += e.second;
				nxt.visit |= ball[nxt.pos];
				auto &c = cand[nxt.pos][nxt.visit];
				if (c.size() < k || nxt.total < c.top()){
					q.push(nxt);
					c.push(nxt.total);
					if (c.size() > k) c.pop();
				}
			}
		}

	fail:;

		if(ans >= 0) cout << ans << endl;
		else cout << "NA" << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 5044
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <iterator>
#include <bitset>
#include <random>
#include <assert.h>
#include <unordered_map>
#include <array>
#include <ctime>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second
#define MP make_pair
#define umap unordered_map

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> P;
typedef unsigned int uint;

const int N = 55;

int d[N][N];
vector<P> G[N];
int ball[N];
int bpos[N];

priority_queue<int> cand[N][1 << 7];

struct state{
	int pos, visit, total;
	bool operator < (const state &r) const{
		return total > r.total;
	}
};

int main(){
	ios::sync_with_stdio(false);

	int n, m, l, k;
	while (cin >> n >> m >> l >> k, n | m | l | k){
		rep(i, N) rep(j, N) d[i][j] = 1 << 29;
		rep(i, N) rep(j, 1 << 7) while (!cand[i][j].empty()) cand[i][j].pop();
		rep(i, N) G[i].clear();
		MEMSET(ball, 0);
		MEMSET(bpos, 0);
		rep(i, m){
			int u, v, c;
			cin >> u >> v >> c;
			--u, --v;
			d[u][v] = d[v][u] = c;
			G[u].push_back(MP(v, c));
			G[v].push_back(MP(u, c));
		}
		int s, g;
		cin >> s >> g;
		--s, --g;
		rep(i, l){
			int b;
			cin >> b;
			ball[--b] = 1 << i;
			bpos[i] = b;
		}
		rep(i, n) rep(j, n) rep(k, n) d[j][k] = min(d[j][k], d[j][i] + d[i][k]);

		priority_queue<state> q;
		q.push({s, 0, 0});

		int cnt = 0, ans = -1;
		if (d[s][g] >= 1 << 29) goto fail;
		while (!q.empty()) {
			auto s = q.top();
			q.pop();

			s.visit |= ball[s.pos];
			auto &pq = cand[s.pos][s.visit];
			if (pq.size() && pq.top() < s.total) continue;

			if (s.pos == g && s.visit + 1 == (1 << l)){
				//cout << s.total << endl;
				if (++cnt == k){
					ans = s.total;
					break;
				}
			}

			for (auto e : G[s.pos]){
				state nxt = s;
				nxt.pos = e.first;
				nxt.total += e.second;
				auto &c = cand[nxt.pos][nxt.visit];
				if (c.size() < k || nxt.total < c.top()){
					q.push(nxt);
					c.push(nxt.total);
					if (c.size() > k) c.pop();
				}
			}
		}

	fail:;
		if(ans >= 0) cout << ans << endl;
		else cout << "NA" << endl;
	}

	return 0;
}
accuracy: 0.07142857142857142
time_ms: 20
memory_kb: 2180
final_rank: 20

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;

typedef pair<int,int> pii;

int solve(int n, int m, int L, int k){
	int mask = (1 << L) - 1;
	vector<vector<pii> > G(n + 1);
	vector<int> bf(n + 1);
	int start, goal, u, v, c, b;
	for(int i = 0; i < m; ++i){
		scanf("%d%d%d", &u, &v, &c);
		G[u].push_back(pii(c, v));
		G[v].push_back(pii(c, u));
	}

	scanf("%d%d", &start, &goal);
	G[0].push_back(pii(0, start));
	goal = goal << L | mask;

	for(int i = 0; i < L; ++i){
		scanf("%d", &b);
		bf[b] |= 1 << i;
	}

	priority_queue<pii> pq;
	pq.push(pii(0, 0));
	vector<int> use((n + 1) << L);
	while(!pq.empty()){
		int d = pq.top().first;
		int st = pq.top().second;
		pq.pop();
		if(++use[st] > k){ continue; }
		if(use[goal] == k){
			return -d;
		}
		
		int p = st >> L;
		int b = st & mask;
		
		for(size_t i = 0; i < G[p].size(); ++i){
			int np = G[p][i].second;
			int nd = d - G[p][i].first;
			int nb = b | bf[np];
			int nst = np << L | nb;
			if(use[nst] < k){
				pq.push(pii(nd, nst));
			}
		}
	}

	return -1;
}

int main(){
	int n, m, L, k;
	while(scanf("%d%d%d%d", &n, &m, &L, &k), n){
		int ans = solve(n, m, L, k);
		printf(ans < 0 ? "NA\n" : "%d\n", ans);
	}
}
accuracy: 1
time_ms: 530
memory_kb: 27780
final_rank: 7

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

struct E{
  int to,cost;
};

int N,M,L,K;
int s,g;
vector<vector<E>> edge;
vector<int> B;
bool input(){
  edge.clear();
  B.clear();
  cin>>N>>M>>L>>K;
  if(!(N||M||L||K))return false;
  edge.resize(N+1);
  for(int i=0;i<M;i++){
    int a,b,c;
    cin>>a>>b>>c;
    edge[a].push_back(E{b,c});
    edge[b].push_back(E{a,c});
  }
  cin>>s>>g;
  for(int i=0;i<L;i++){
    int tmp;
    cin>>tmp;
    B.push_back(tmp);
  }
  return true;
}

struct S{
  int pos,cost,b;
}; 
bool operator<(S a,S b){
  return a.cost>b.cost;
}

vector<vector<int>> dp;
int solve(){
  priority_queue<S> que;
  que.push(S{s,0,0});
  
  dp.clear();
  dp.resize(N+1);
  for(int i=0;i<dp.size();i++){
    dp[i].resize(1<<L+1);
  }
  
  while(!que.empty()){
    S now = que.top();que.pop();
    for(int i=0;i<B.size();i++){
      if(now.pos == B[i]){
        now.b = now.b | (1<<i);
      }
    }
    if(!(dp[now.pos][now.b]<K+1))continue;
    dp[now.pos][now.b]++;
    if(now.pos == g && now.b==((1<<L)-1) ){
      if(dp[now.pos][now.b] == K){
        return now.cost;
      }
    }

    for(int i=0;i<edge[now.pos].size();i++){
      que.push(S{edge[now.pos][i].to ,now.cost + edge[now.pos][i].cost, now.b});
    }
  }
  return -1;
}

int main(){
  while(input()){
    int ans = solve();
    if(ans<0){
      cout<<"NA"<<endl;
    }else {
      cout<<ans<<endl;
    }
  }
}
accuracy: 1
time_ms: 1010
memory_kb: 76996
final_rank: 15

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#include <utility>
#include <functional>
using namespace std;

typedef pair<int,int> pii;

int solve(int n, int m, int L, int k){
	int u, v, c, start, goal, b;
	vector<vector<pii> > G(n + 2);
	for(int i = 0; i < m; ++i){
		scanf("%d%d%d", &u, &v, &c);
		G[u].push_back(pii(c, v));
		G[v].push_back(pii(c, u));
	}
	scanf("%d%d", &start, &goal);
	G[0].push_back(pii(0, start));
	G[goal].push_back(pii(0, n + 1));

	vector<int> bnum(n + 2, -1);
	vector<int> use((n + 2) << L, 0);
	for(int i = 0; i < L; ++i){
		scanf("%d", &b);
		bnum[b] = i;
	}

	goal = ((n + 2) << L) - 1;


	priority_queue<pii,vector<pii>,greater<pii> > pq;
	vector<vector<int> > ds((n + 2) << L);
	pq.push(pii(0, 0));
	ds[0].push_back(0);
	while(!pq.empty()){
		pii p = pq.top();
		pq.pop();
		int d = p.first;
		int st = p.second;
		int now = st >> L;
		b = st & ((1 << L) - 1);

		if(use[st] >= ds[st].size() || ds[st][use[st]] != d){
			continue;
		}
		++use[st];

		for(size_t i = 0; i < G[now].size(); ++i){
			int next = G[now][i].second;
			int nd = d + G[now][i].first;
			int nb = b;
			if(bnum[next] != -1){
				nb |= 1 << bnum[next];
			}

			int nst = next << L | nb;
			int ord = upper_bound(ds[nst].begin(), ds[nst].end(), nd)
				- ds[nst].begin();

			ds[nst].push_back(0);
			for(int j = ds[nst].size() - 1; j > ord; --j){
				ds[nst][j] = ds[nst][j - 1];
			}
			ds[nst][ord] = nd;
			if(ds[nst].size() > k){
				ds[nst].pop_back();
			}

			if(ord != k){
				pq.push(pii(nd, nst));
			}
		}
	}

	return ds[goal].size() == k ? ds[goal].back() : -1;
}

int main(){
	int n, m, L, k;
	while(scanf("%d%d%d%d", &n, &m, &L, &k), n){
		int ans = solve(n, m, L, k);
		printf(ans < 0 ? "NA\n" : "%d\n", ans);
	}
}
accuracy: 1
time_ms: 460
memory_kb: 3108
final_rank: 3

code_snippet: #include<stdio.h>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define rep(i, e) for ( int i = 0; i < (int)e; i++ )
#define MAX 50
#define MAXK 10
#define MAXL 7
#define INFTY (1<<21)

class Edge{
    public:
    int v, cost;
    Edge(){}
    Edge( int v, int cost): v(v), cost(cost){}
};

class State{
    public:
	int u, b, cost;
    State(){}
    State(int u, int b, int cost):u(u), b(b), cost(cost){}

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

vector<Edge> G[MAX];
int D[MAX][MAXK][1<<MAXL];
bool V[MAX][MAXK][1<<MAXL];
int B[MAX];

int size, source, target, K, L;

void kthDijkstra(){
    priority_queue<State> PQ;
    int LV[MAX][1<<L]; // level

    rep(i, size) rep(k, K) rep(l, (1<<L)){
	D[i][k][l] = INFTY;
	V[i][k][l] = false;
    }
    rep(i, size) rep(l, (1<<L)) LV[i][l] = 0;

    int bs = 0;
    if ( B[source] != -1 ) bs = (bs | (1<<B[source]));

    D[source][0][bs] = 0;
    V[source][0][bs] = true;
    PQ.push(State(source, bs, 0));

    State s;
    while(!PQ.empty()){
	s = PQ.top(); PQ.pop();
	if ( LV[s.u][s.b] >= K ) continue;
	V[s.u][LV[s.u][s.b]][s.b] = true;
	D[s.u][LV[s.u][s.b]++][s.b] = s.cost;
	
	rep(i, G[s.u].size() ){
	    int v = G[s.u][i].v;
	    bs = s.b;
	    if ( B[v] != -1 ) bs = (bs | (1<<B[v]));
	    if ( LV[v][bs] <= K ){
		if ( !V[v][LV[v][bs]][bs] ){
		    PQ.push(State(v, bs, s.cost + G[s.u][i].cost ));
		}
	    }
	}
    }
}

void compute(){
    kthDijkstra();
    if ( D[target][K-1][(1<<L)-1] == INFTY ) printf("NA\n");
    else printf("%d\n", D[target][K-1][(1<<L)-1]);
}

bool input(){
    int m, s, t, c;
    scanf("%d %d %d %d", &size, &m, &L, &K);
    if ( size == 0 && m == 0 && L == 0 && K == 0) return false;

    rep(i, size) B[i] = -1;
    rep(i, size) G[i].clear();
    rep(i, m){
	scanf("%d %d %d", &s, &t, &c);
	s--; t--;
	G[s].push_back(Edge(t, c));
	G[t].push_back(Edge(s, c));
    }

    scanf("%d %d",  &source, &target);
    source--; target--;
    rep(i, L){
	int p;
	scanf("%d", &p);
	B[p-1] = i;
    }
    return true;
}

int main(){
    while(input()) compute();
    return 0;
}
accuracy: 1
time_ms: 2970
memory_kb: 50236
final_rank: 18

code_snippet: #include<algorithm>
#include <cstring>
#include <iostream>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<utility>
#include<stack>
#include <complex>
#include <cassert>
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();
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
typedef int Weight;
struct Edge {
  int src,dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src),dst(dst),weight(weight) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.weight > f.weight;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
Weight k_shortestPath(const Graph &g, int s, int t, int k) {
  const int n = g.size();
  Graph h(n);
  REP(u,n)FOR(e,g[u])
    h[e->dst].push_back(Edge(e->dst,e->src,e->weight));

  vector<Weight> d(n,INF); d[t] = 0;
  vector<int> p(n,-1);
  priority_queue<Edge> Q; Q.push(Edge(t,t,0));

  while(!Q.empty()) {
    Edge e = Q.top(); Q.pop();
    if (p[e.dst] >= 0)continue;
    p[e.dst] = e.src;
    FOR(f,h[e.dst]) if (d[f->dst] > e.weight + f->weight) {
      d[f->dst] = e.weight + f->weight;
      Q.push(Edge(f->src, f->dst, e.weight + f->weight));
    }
  }
  if (p[s] == -1) return -1;
  int l = 0;
  priority_queue<Edge> R; R.push(Edge(-1,s,0));
  while(!R.empty()) {
    Edge e = R.top(); R.pop();
    if (e.dst == t && ++l == k) return e.weight + d[s];
    FOR(f,g[e.dst])
      R.push(Edge(f->src,f->dst,e.weight + f->weight - d[f->src] + d[f->dst]));
  }
  return -1;
}

int n;
int l;

int NODE(int i, int S) {
  return i*(1<<l)+S;
}

int f[100];
  
int main() {
  int m,k;
  while(cin>>n>>m>>l>>k,n||m||l||k) {
    Graph tg(n);
    Graph g(n*(1<<l));
    REP(i,m) {
      int a, b, c;
      cin >> a >> b >> c;
      a--;b--;
      tg[a].push_back(Edge(a,b,c));
      tg[b].push_back(Edge(b,a,c));
    }
    int s,t;
    cin >> s >> t;
    s--;t--;
    memset(f,-1,sizeof(f));
    REP(i,l) {
      int a;
      cin >> a; a--;
      f[a] = i;
    }
    REP(i,n) {
      FOR(it, tg[i]) {
        int a = i;
        int b = it->dst;
        int c = it->weight;
        REP(S,1<<l) {
          if (f[i]!=-1 && !(S>>f[i]&1)) continue;
          int A = NODE(a,S);
          int T = S;
          if (f[b]!=-1) T |= 1<<f[b];
          int B = NODE(b,T);
          g[A].push_back(Edge(A,B,c));
        }
      }
    }
    REP(i,n*(1<<l)) {
      FOR(it, g[i]) {
        // cout << i <<" " << it->dst << " " << it->weight << endl;
      }
    }
    int S = 0;
    if (f[s] != -1) S|=1<<f[s];
    
    int ans = k_shortestPath(g,NODE(s,S),NODE(t,(1<<l)-1),k);
    if (ans == -1) cout << "NA" << endl;
    else cout << ans << endl;
  }
}
accuracy: 1
time_ms: 170
memory_kb: 11584
final_rank: 4