Problem:
Problem D:
Long Distance Taxi
A taxi driver, Nakamura, was so delighted because he got a passenger who wanted to go to a
city thousands of kilometers away. However, he had a problem. As you may know, most taxis in
Japan run on liquefied petroleum gas (LPG) because it is cheaper than gasoline. There are more
than 50,000 gas stations in the country, but less than one percent of them sell LPG. Although
the LPG tank of his car was full, the tank capacity is limited and his car runs 10 kilometer per
liter, so he may not be able to get to the destination without filling the tank on the way. He
knew all the locations of LPG stations.
Your task is to write a program that finds the best way from the current location to the destination without running out of gas.
Input
The input consists of several datasets, and each dataset is in the following format.
N M cap
src dest
c
1,1
c
1,2
d
1
c
2,1
c
2,2
d
2
.
.
.
c
N,1
c
N,2
d
N
s
1
s
2
.
.
.
s
M
The first line of a dataset contains three integers (
N, M, cap
), where
N
is the number of roads
(1 ≤
N
≤ 3000),
M
is the number of LPG stations (1≤
M
≤ 300), and
cap
is the tank capacity
(1 ≤
cap
≤ 200) in liter. The next line contains the name of the current city (
src
) and the name
of the destination city (
dest
). The destination city is always different from the current city.
The following
N
lines describe roads that connect cities. The road i (1 ≤
i
≤ N) connects two
different cities
c
i,1
and
c
i,2
with an integer distance
d
i
(0 <
d
i
≤ 2000) in kilometer, and he can
go from either city to the other. You can assume that no two different roads connect the same
pair of cities. The columns are separated by a single space. The next
M
lines (
s
1
,
s
2
,...,
s
M
) indicate the names of the cities with LPG station. 
You can assume that a city with LPG station has at least one road.
The name of a city has no more than 15 characters. Only English alphabet ('A' to 'Z' and 'a'
to 'z', case sensitive) is allowed for the name.
A line with three zeros terminates the input.
Output
For each dataset, output a line containing the length (in kilometer) of the shortest possible
journey from the current city to the destination city. If Nakamura cannot reach the destination,
output "-1" (without quotation marks). You must not output any other characters.
The actual tank capacity is usually a little bit larger than that on the specification sheet, so
you can assume that he can reach a city even when the remaining amount of the gas becomes
exactly zero. In addition, you can always fill the tank at the destination so you do not have to
worry about the return trip.
Sample Input
6 3 34
Tokyo Kyoto
Tokyo Niigata 335
Tokyo Shizuoka 174
Shizuoka Nagoya 176
Nagoya Kyoto 195
Toyama Niigata 215
Toyama Kyoto 296
Nagoya
Niigata
Toyama
6 3 30
Tokyo Kyoto
Tokyo Niigata 335
Tokyo Shizuoka 174
Shizuoka Nagoya 176
Nagoya Kyoto 195
Toyama Niigata 215
Toyama Kyoto 296
Nagoya
Niigata
Toyama
0 0 0
Output for the Sample Input
846
-1

Submitted solutions:

code_snippet: #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 6000;
const int maxm = 6090;
const int inf = ~0u >> 2;

struct Edge{
	int v, w;
	Edge() {}
	Edge(int v, int w) {
		this->v = v;	this->w = w;
	}
};

int n, m, gas, ncnt;
vector<int> gast;
vector<Edge> g1[maxn], g2[maxm];
map<string, int> mp;

void addNode(string s)
{
	if(!mp[s])	mp[s] = ++ncnt;
}

void addEdge(int u, int v, int w)
{
	g1[u].push_back(Edge(v, w));
	g1[v].push_back(Edge(u, w));
}

void spfa(int x, int dis[], vector<Edge> g[])
{
	queue<int> q;
	bool inqueue[maxn];
	memset(inqueue, 0, sizeof(inqueue));
	inqueue[x] = 1;	q.push(x); dis[x] = 0;
	while(!q.empty()) {
		int tmp = q.front();	q.pop();	inqueue[tmp] = false;
		for(int i = 0; i < g[tmp].size(); i++) {
			int v = g[tmp][i].v, w = g[tmp][i].w;
			if(dis[tmp]+w < dis[v]) {
				dis[v] = dis[tmp]+w;
				if(!inqueue[v]) {
					q.push(v);
					inqueue[v] = true;;
				}
			}	
		}
	}	
}

int main()
{
#ifdef LOCAL
	freopen("D.in", "r", stdin);
#endif
	while(scanf("%d%d%d", &m, &n, &gas) != EOF) {
		if(m == 0 && n == 0)	break;
		ncnt = 0;
		char stmp[maxm], estmp[maxm]; 
		gast.clear();
		mp.clear();
		for(int i = 0; i < maxn; i++)	g1[i].clear();
		for(int i = 0; i < maxm; i++)	g2[i].clear();
		scanf("%s%s", stmp, estmp);
		addNode(stmp);	addNode(estmp);
		for(int i = 0; i < m; i++) {
			int w;
			scanf("%s%s%d", stmp, estmp, &w);
			addNode(stmp);	addNode(estmp);
			addEdge(mp[stmp], mp[estmp], w);
		}
		gast.push_back(1);	gast.push_back(2);
		for(int i = 1; i <= n; i++) {
		//if one vertex is unique, ignore it
			scanf("%s", stmp);
			if(mp[stmp])	gast.push_back(mp[stmp]);
		}
		//calc single-point shortest path for every gas station and set-up point
		//rebuild a graph with vertices including stations and beginning and end point
		for(int i = 0; i < gast.size(); i++) {
			int x = gast[i];
			int dis[maxn];
			fill(dis, dis+ncnt+1, inf);
			spfa(x, dis, g1);
			for(int j = 0; j < gast.size(); j++)
				if(dis[gast[j]] <= gas*10) 	g2[i].push_back(Edge(j, dis[gast[j]]));
		}
		int dis[maxm];
		fill(dis, dis+gast.size()+1, inf);
		spfa(0, dis, g2);	
		printf("%d\n", dis[1] != inf ? dis[1] : -1);
	}
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 5488
final_rank: 1

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=3000+10;
map<string,int>mp;
struct Edge
{
    int v,w,next;
    Edge(){}
    Edge(int v,int w,int next):v(v),w(w),next(next){}
}edges[maxn<<2];
int head[maxn<<1],d[maxn<<1][2010],nEdge;
bool flag[maxn<<1],inq[maxn<<1][2010];
void AddEdges(int u,int v,int w)
{
    edges[++nEdge]=Edge(v,w,head[u]);
    head[u]=nEdge;
    edges[++nEdge]=Edge(u,w,head[v]);
    head[v]=nEdge;
}
int spfa(int s,int t,int cap)
{
    memset(d,0x3f,sizeof(d));
    memset(inq,0,sizeof(inq));
    cap*=10;
    d[s][cap]=0;
    queue<pair<int,int> >q;
    q.push(make_pair(s,cap));
    pair<int,int>pii;
    int u,st;
    while(!q.empty())
    {
        pii=q.front();q.pop();
        u=pii.first;st=pii.second;
        inq[u][st]=false;
        for(int k=head[u];k!=-1;k=edges[k].next)
        {
            int v=edges[k].v;
            int cost=edges[k].w;
            if(st>=cost&&d[v][st-cost]>d[u][st]+cost)
            {
                d[v][st-cost]=d[u][st]+cost;
                if(!inq[v][st-cost]) {inq[v][st-cost]=true;q.push(make_pair(v,st-cost));}
            }
            if(flag[u])
            {
                if(cap>=cost&&d[v][cap-cost]>d[u][st]+cost)
                {
                    d[v][cap-cost]=d[u][st]+cost;
                    if(!inq[v][cap-cost]) {inq[v][cap-cost]=true;q.push(make_pair(v,cap-cost));}
                }
            }
        }
    }
    int res=inf;
    for(int i=0;i<=cap;++i)
        res=min(res,d[t][i]);
    return res==inf?-1:res;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    char str[30],str2[30];
    int n,m,s,t,cap,N;
    while(~scanf("%d%d%d",&n,&m,&cap))
    {
        if(n==0&&m==0&&cap==0) break;
        mp.clear();
        N=0;
        scanf("%s",str);
        s=mp[(string)str]=++N;
        scanf("%s",str);
        t=mp[(string)str]=++N;
        memset(head,0xff,sizeof(head));
        nEdge=-1;
        memset(flag,0,sizeof(flag));
        int u,v,w;
        for(int i=0;i<n;++i)
        {
            scanf("%s%s%d",str,str2,&w);
            if(mp[(string)str]) u=mp[(string)str];
            else u=mp[(string)str]=++N;
            if(mp[(string)str2]) v=mp[(string)str2];
            else v=mp[(string)str2]=++N;
            AddEdges(u,v,w);
        }
        for(int i=0;i<m;++i)
        {
            scanf("%s",str);
            flag[mp[(string)str]]=true;
        }
        int ans=spfa(s,t,cap);
        printf("%d\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 75740
final_rank: 11

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

using namespace std;

typedef long long LL;


const int oo=INT_MAX>>1;
struct node{
	int u,x,w;
	node(int _u,int _x,int _w){
		u=_u; x=_x; w=_w;
	}
	bool operator<(const node &t)const{
		return w>t.w;
	}
};
priority_queue<node> Q;
vector< pair<int,int> > a[13000];
int dis[6007][2007],N;
bool vis[6007][2007],b[6100];
map<string,int> mm;

int get(string s){
	if (mm[s]) return mm[s];
	mm[s]=++N; a[N].clear();
	return N;
}

int main(){
	int M,c,lim,u,v,d,i,j;
	while (scanf("%d%d%d",&M,&c,&lim), M || c || lim){
		lim*=10;
		char s[100],t[100];
		mm.clear(); N=0;
		scanf("%s%s",s,t); get(s); get(t);
		while (M--){
			scanf("%s%s%d",s,t,&d);
			u=get(s); v=get(t);
			a[u].push_back(make_pair(v,d)); a[v].push_back(make_pair(u,d));
		}
		for (i=1;i<=N;i++){
			b[i]=0;
			for (j=0;j<=lim;j++){
				dis[i][j]=oo; vis[i][j]=0;
			}
		}
		while (c--){
			scanf("%s",s); b[get(s)]=1;
		}
		dis[1][lim]=0;
		Q.push(node(1,lim,0));
		int x,y;
		while (!Q.empty()){
			u=Q.top().u; x=Q.top().x; Q.pop();
			if (vis[u][x]) continue;
			vis[u][x]=1;
			for (vector< pair<int,int> >::iterator ii=a[u].begin();ii!=a[u].end();ii++){
				v=ii->first; d=ii->second;
				if (d>x) continue;
				y=b[v]?lim:x-d;
				if (dis[u][x]+d<dis[v][y]){
					dis[v][y]=dis[u][x]+d;
					Q.push(node(v,y,dis[v][y]));
				}
			}
		}
		int ans=oo;
		for (i=0;i<=lim;i++){
			ans=min(ans,dis[2][i]);
		}
		printf("%d\n",ans==oo?-1:ans);
	}
}
accuracy: 1
time_ms: 610
memory_kb: 88728
final_rank: 14

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <bitset>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define FI first
#define SE second
using namespace std;
typedef long long LL;
const int maxn=6005;
int n,m,C;
map <string,int> mp;
map <string,int>::iterator it;
int head[maxn];
struct Edge
{
    int next,to,len;
}ed[maxn*2];
int ecnt,label;

inline void init()
{
    ecnt=label=0;
    memset(head,-1,sizeof(head));
    mp.clear();
}

inline void addedge(int u,int v,int l)
{
    ed[ecnt].next=head[u];
    ed[ecnt].to=v;
    ed[ecnt].len=l;
    head[u]=ecnt++;
}

inline int add(char *s)
{
    it=mp.find(s);
    if(it!=mp.end()) return it->second;
    mp.insert(make_pair(s,label));
    return label++;
}

char s1[25],s2[25];
struct Node
{
    int u,c,dis;
    inline Node() {}
    inline Node(int _u,int _c,int _dis)
    {
        u=_u; c=_c; dis=_dis;
    }
    bool operator <(const Node &a)const
    {
        return dis>a.dis;
    }
};
priority_queue <Node> Q;

int dp[6005][2005];
bool done[6005][2005];
bool LPG[6005];
inline int Dijkstra(int S,int T)
{
    while(!Q.empty()) Q.pop();
    C*=10;
    for(int i=0;i<label;++i) for(int j=0;j<=C;++j)
    {
        dp[i][j]=INF;
        done[i][j]=0;
    }
    dp[S][C]=0;
    Q.push(Node(S,C,0));
    Node t;
    while(!Q.empty())
    {
        t=Q.top(); Q.pop();
        if(t.u==T) return t.dis;
        if(done[t.u][t.c]) continue;
        for(int e=head[t.u];~e;e=ed[e].next)
        {
            int v=ed[e].to;
            if(t.c<ed[e].len) continue;
            int nc=t.c-ed[e].len;
            if(LPG[v]) nc=C;
            if(dp[v][nc]>t.dis+ed[e].len)
            {
                dp[v][nc]=t.dis+ed[e].len;
                Q.push(Node(v,nc,dp[v][nc]));
            }
        }
    }
    return -1;
}

int main()
{
    while(scanf("%d%d%d",&n,&m,&C)&&n)
    {
        init();
        scanf("%s%s",s1,s2);
        int S=add(s1),T=add(s2);
        for(int i=0;i<n;++i)
        {
            int d;
            scanf("%s%s%d",s1,s2,&d);
            if(d>C*10) continue;
            int u=add(s1),v=add(s2);
            addedge(u,v,d);
            addedge(v,u,d);
        }
        memset(LPG,0,sizeof(LPG));
        for(int i=0;i<m;++i)
        {
            scanf("%s",s1);
            LPG[add(s1)]=1;
        }
        printf("%d\n",Dijkstra(S,T));
    }
    return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 87140
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long INF = 4e18;

int main() {
    while (true) {
        int N, M, cap;
        if (!(cin >> N >> M >> cap) || (N == 0 && M == 0 && cap == 0)) break;
        string srcName, dstName; cin >> srcName >> dstName;

        unordered_map<string, int> id;
        vector<vector<pair<int,int>>> g;

        auto getID = [&](const string& s) -> int {
            auto it = id.find(s);
            if (it != id.end()) return it->second;
            int idx = id.size();
            id[s] = idx;
            g.emplace_back();
            return idx;
        };

        for (int i = 0; i < N; ++i) {
            string a, b; int d; cin >> a >> b >> d;
            int u = getID(a), v = getID(b);
            g[u].push_back({v,d});
            g[v].push_back({u,d});
        }

        vector<int> station;
        station.reserve(M+2);
        station.push_back(getID(srcName));
        int dstID = getID(dstName);
        if (dstID != station[0]) station.push_back(dstID);

        for (int i = 0; i < M; ++i) {
            string s; cin >> s;
            int idS = getID(s);
            if (idS != station[0] && idS != dstID) station.push_back(idS);
        }

        int R = cap * 10;
        int K = station.size();
        vector<vector<long long>> meta(K, vector<long long>(K, INF));

        auto dijkstra_cut = [&](int start){
            vector<long long> dist(g.size(), INF);
            using P=pair<long long,int>; priority_queue<P, vector<P>, greater<P>> pq;
            dist[start]=0; pq.push({0,start});
            while(!pq.empty()){
                auto [d,u]=pq.top(); pq.pop();
                if(d!=dist[u] || d>R) continue;
                for(auto [v,w]:g[u]){
                    if(d+w<dist[v] && d+w<=R){
                        dist[v]=d+w; pq.push({dist[v],v});
                    }
                }
            }
            return dist;
        };

        vector<vector<long long>> allDist;
        for(int i=0;i<K;++i) allDist.push_back(dijkstra_cut(station[i]));

        for(int i=0;i<K;++i)
            for(int j=0;j<K;++j)
                if(allDist[i][station[j]]<=R)
                    meta[i][j]=allDist[i][station[j]];

        vector<long long> dmeta(K,INF);
        using P=pair<long long,int>; priority_queue<P,vector<P>,greater<P>> pq;
        dmeta[0]=0; pq.push({0,0});
        while(!pq.empty()){
            auto [d,u]=pq.top(); pq.pop();
            if(d!=dmeta[u]) continue;
            for(int v=0;v<K;++v)
                if(meta[u][v]<INF && d+meta[u][v]<dmeta[v]){
                    dmeta[v]=d+meta[u][v];
                    pq.push({dmeta[v],v});
                }
        }

        long long ans = dmeta[1];
        cout << (ans==INF?-1:ans) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 11340
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 4e18;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int N, M, cap;
        if (!(cin >> N >> M >> cap) || (N == 0 && M == 0 && cap == 0)) break;
        string srcName, dstName; cin >> srcName >> dstName;

        unordered_map<string, int> id;
        vector<vector<pair<int,int>>> g;             // id -> {next, dist}

        auto getID = [&](const string& s) -> int {
            auto it = id.find(s);
            if (it != id.end()) return it->second;
            int idx = id.size();
            id[s] = idx;
            g.emplace_back();
            return idx;
        };

        for (int i = 0; i < N; ++i) {
            string a, b; int d; cin >> a >> b >> d;
            int u = getID(a), v = getID(b);
            g[u].push_back({v,d});
            g[v].push_back({u,d});
        }

        vector<int> station;
        station.reserve(M+2);
        station.push_back(getID(srcName));
        int dstID = getID(dstName);
        if (dstID != station[0]) station.push_back(dstID);

        for (int i = 0; i < M; ++i) {
            string s; cin >> s;
            int idS = getID(s);
            if (idS != station[0] && idS != dstID) station.push_back(idS);
        }

        int R = cap * 10;
        int K = station.size();
        vector<vector<ll>> meta(K, vector<ll>(K, INF));

        auto dijkstra_cut = [&](int start){
            vector<ll> dist(g.size(), INF);
            using P=pair<ll,int>; priority_queue<P, vector<P>, greater<P>> pq;
            dist[start]=0; pq.push({0,start});
            while(!pq.empty()){
                auto [d,u]=pq.top(); pq.pop();
                if(d!=dist[u] || d>R) continue;
                for(auto [v,w]:g[u]){
                    if(d+w<dist[v] && d+w<=R){
                        dist[v]=d+w; pq.push({dist[v],v});
                    }
                }
            }
            return dist;
        };

        vector<vector<ll>> allDist;
        for(int i=0;i<K;++i) allDist.push_back(dijkstra_cut(station[i]));

        for(int i=0;i<K;++i)
            for(int j=0;j<K;++j)
                if(allDist[i][station[j]]<=R)
                    meta[i][j]=allDist[i][station[j]];

        vector<ll> dmeta(K,INF);
        using P=pair<ll,int>; priority_queue<P,vector<P>,greater<P>> pq;
        dmeta[0]=0; pq.push({0,0});
        while(!pq.empty()){
            auto [d,u]=pq.top(); pq.pop();
            if(d!=dmeta[u]) continue;
            for(int v=0;v<K;++v)
                if(meta[u][v]<INF && d+meta[u][v]<dmeta[v]){
                    dmeta[v]=d+meta[u][v];
                    pq.push({dmeta[v],v});
                }
        }

        ll ans = dmeta[1];
        cout << (ans==INF?-1:ans) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 11464
final_rank: 4

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
////////////////////////////////////////////
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while (true)
    {
        ll n, m, cap;
        cin >> n >> m >> cap;
        if (n == 0)
        {
            break;
        }
        string S, G;
        cin >> S >> G;
        set<string> st;
        st.insert(S);
        st.insert(G);
        vector<string> a(n), b(n);
        vector<ll> c(n);
        rep(i, 0, n)
        {
            cin >> a[i] >> b[i] >> c[i];
            st.insert(a[i]);
            st.insert(b[i]);
        }
        ll C = 0;
        map<string, ll> mp;
        for (auto i : st)
        {
            mp[i] = C;
            C++;
        }
        vector<vector<pair<ll, ll>>> g(C);
        rep(i, 0, n)
        {
            g[mp[a[i]]].push_back(pr(mp[b[i]], c[i]));
            g[mp[b[i]]].push_back(pr(mp[a[i]], c[i]));
        }
        vector<bool> sta(C);
        rep(i, 0, m)
        {
            string x;
            cin >> x;
            sta[mp[x]] = true;
        }
        vector<vector<ll>> d(C, vector<ll>(cap * 10 + 1, inf));
        d[mp[S]][cap * 10] = 0;
        using T = pair<ll, pair<ll, ll>>;
        priority_queue<T, vector<T>, greater<T>> que;
        que.push(pr(0, pr(mp[S], cap * 10)));
        while (!que.empty())
        {
            ll X = que.top().first;
            ll Y = que.top().second.first;
            ll Z = que.top().second.second;
            que.pop();
            if (d[Y][Z] != X)
            {
                continue;
            }
            rep(i, 0, g[Y].size())
            {
                ll nxt = g[Y][i].first;
                ll cost = g[Y][i].second;
                if (Z >= cost)
                {
                    if (sta[nxt])
                    {
                        if (d[nxt][cap * 10] > X + cost)
                        {
                            d[nxt][cap * 10] = X + cost;
                            que.push(pr(d[nxt][cap * 10], pr(nxt, cap * 10)));
                        }
                    }
                    else
                    {
                        if (d[nxt][Z - cost] > X + cost)
                        {
                            d[nxt][Z - cost] = X + cost;
                            que.push(pr(d[nxt][Z - cost], pr(nxt, Z - cost)));
                        }
                    }
                }
            }
        }
        ll ans = inf;
        rep(i, 0, cap * 10 + 1)
        {
            chmin(ans, d[mp[G]][i]);
        }
        if (ans == inf)
        {
            cout << -1 << endl;
        }
        else
        {
            cout << ans << endl;
        }
    }
}
accuracy: 1
time_ms: 1160
memory_kb: 101768
final_rank: 16

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

using ll = long long;
#define rep(i,n) for(int i=0;i<n;i++)

map<string,int> MP;
vector<vector<array<int,2>>> G;
int rt(string S){
    if(!MP.count(S)){
        MP[S]=MP.size();
        G.push_back({});
    }
    return MP[S];
}

void solve(int N,int M,int C){
    MP.clear();
    G.clear();
    string s,t;
    cin>>s>>t;
    int S=rt(s),T=rt(t);
    rep(i,N){
        cin>>s>>t;
        int U=rt(s),V=rt(t),d;
        cin>>d;
        G[U].push_back({V,d});
        G[V].push_back({U,d});
    }
    set<int> LP;
    rep(i,M){
        string s;
        cin>>s;
        LP.insert(rt(s));
    }

    N=MP.size();
    vector<vector<ll>> D(N,vector<ll>(C*10+1,1e18));
    D[S][0]=0;
    priority_queue<array<ll,3>,vector<array<ll,3>>,greater<array<ll,3>>> Q;
    Q.push({0,S,0});
    vector<vector<bool>> seen(N,vector<bool>(C*10+1,0));
    ll an=1e18;
    while(!Q.empty()){
        auto p=Q.top();
        Q.pop();
        if(seen[p[1]][p[2]])continue;
        seen[p[1]][p[2]]=1;
        if(p[1]==T)an=min(an,p[0]);
        for(auto [v,d]:G[p[1]]){
            ll nc=p[2]+d,nd=p[0]+d;
            if(nc>C*10)continue;
            if(LP.count(v))nc=0;
            if(seen[v][nc])continue;
            if(D[v][nc]>nd){
                D[v][nc]=nd;
                Q.push({nd,v,nc});
            }
        }
    }
    cout<<(an<1e17?an:-1)<<endl;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N,M,C;
    while(cin>>N>>M>>C,N+M+C!=0)solve(N,M,C);
}
accuracy: 1
time_ms: 1380
memory_kb: 101432
final_rank: 18

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

using ll = long long;
#define rep(i,n) for(int i=0;i<n;i++)
#define rep2(i,s,t) for(int i=s;i<t;i++)

using vi = vector<int>;

int rt(map<string,int> &MP,string S,vector<vector<array<int,2>>> &G){
    if(!MP.count(S)){
        MP[S]=MP.size();
        G.push_back({});
    }
    return MP[S];
}

void solve(int N,int M,int C){
    map<string,int> MP;
    vector<vector<array<int,2>>> G;
    string s,t;
    cin>>s>>t;
    int S=rt(MP,s,G),T=rt(MP,t,G);
    rep(i,N){
        string u,v;
        cin>>u>>v;
        int U=rt(MP,u,G),V=rt(MP,v,G),d;
        cin>>d;
        G[U].push_back({V,d});
        G[V].push_back({U,d});
    }
    set<int> LP;
    rep(i,M){
        string s;
        cin>>s;
        LP.insert(rt(MP,s,G));
    }

    N=MP.size();
    vector<vector<ll>> D(N,vector<ll>(C*10+1,1e18));
    D[S][0]=0;
    priority_queue<array<ll,3>,vector<array<ll,3>>,greater<array<ll,3>>> Q;
    Q.push({0,S,0});
    vector<vector<bool>> seen(N,vector<bool>(C*10+1,0));
    while(!Q.empty()){
        auto p=Q.top();
        Q.pop();
        if(seen[p[1]][p[2]])continue;
        seen[p[1]][p[2]]=1;
        for(auto [v,d]:G[p[1]]){
            ll nc=p[2]+d;
            if(nc>C*10)continue;
            ll nd=p[0]+d;
            if(LP.count(v))nc=0;
            if(seen[v][nc])continue;
            if(D[v][nc]>nd){
                D[v][nc]=nd;
                Q.push({nd,v,nc});
            }
        }
    }
    ll an=1e18;
    rep(i,C*10+1)an=min(an,D[T][i]);
    cout<<(an<1e17?an:-1)<<endl;
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int N,M,C;
    while(cin>>N>>M>>C,N+M+C!=0)solve(N,M,C);
}
accuracy: 1
time_ms: 1400
memory_kb: 102336
final_rank: 19

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct UnionFind{
    vector<int> par; int n;
    UnionFind(){}
    UnionFind(int _n):par(_n,-1),n(_n){}
    int root(int x){return par[x]<0?x:par[x]=root(par[x]);}
    bool same(int x,int y){return root(x)==root(y);}
    int size(int x){return -par[root(x)];}
    bool unite(int x,int y){
        x=root(x),y=root(y); if(x==y)return false;
        if(size(x)>size(y))swap(x,y);
        par[y]+=par[x]; par[x]=y; n--; return true;
    }
};

/**
 * @brief Union Find
 */

vector<int> MakeDist(vector<vector<pair<int,int>>>& G, int S) {
    int N = G.size();
    vector<int> DP(N,inf);
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
    DP[S] = 0;
    PQ.push({0,S});
    while(!PQ.empty()) {
        auto [D,P] = PQ.top();
        PQ.pop();
        if (DP[P] < D) continue;
        for (auto E : G[P]) {
            int NP = E.first, ND = E.second + D;
            if (chmin(DP[NP],ND)) {
                PQ.push({ND,NP});
            }
        }
    }
    return DP;
}

int main() {
while(1) {
    int M, K, L;
    cin >> M >> K >> L;
    if (M == 0) return 0;
    L *= 10;
    map<string,int> mp;
    int Cur = 0;
    string S;
    cin >> S;
    mp[S] = 0;
    cin >> S;
    mp[S] = 1;
    Cur = 2;
    vector<int> A(M), B(M), D(M);
    rep(i,0,M) {
        string T;
        cin >> S >> T >> D[i];
        if (mp.count(S)) A[i] = mp[S];
        else mp[S] = A[i] = Cur, Cur++;
        if (mp.count(T)) B[i] = mp[T];
        else mp[T] = B[i] = Cur, Cur++;
    }
    vector<int> C(K+2);
    rep(i,0,K) {
        cin >> S;
        if (mp.count(S)) C[i] = mp[S];
        else mp[S] = C[i] = Cur, Cur++;
    }
    C[K] = 0,C[K+1] = 1;
    UNIQUE(C);
    int N = Cur;
    K = C.size();
    vector<vector<pair<int,int>>> G(N);
    rep(i,0,M) G[A[i]].push_back({B[i],D[i]}), G[B[i]].push_back({A[i],D[i]});
    vector<vector<int>> Dist(K,vector<int>(K,inf));
    rep(i,0,K) {
        vector<int> DP = MakeDist(G,C[i]);
        rep(j,0,K) {
            Dist[i][j] = DP[C[j]];
        }
    }
    rep(i,0,K) {
        rep(j,0,K) {
            if (Dist[i][j] > L) Dist[i][j] = inf;
        }
    }
    rep(k,0,K) {
        rep(i,0,K) {
            rep(j,0,K) {
                chmin(Dist[i][j], Dist[i][k] + Dist[k][j]);
            }
        }
    }
    cout << (Dist[0][1] == inf ? -1 : Dist[0][1]) << endl;
}
}
accuracy: 1
time_ms: 640
memory_kb: 4004
final_rank: 6

code_snippet: #include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;
using ll = long long;

class Node {
   public:
	string city;
	int gas; // [deciliter]
	int dist;

	Node(const string& city, const int& gas, const int& dist)
		: city(city), gas(gas), dist(dist) {};

	bool operator<(const Node& b) const {
		return (this->dist > b.dist);
	}
};

// cap [deciliter]
ll ShortestWay(const int& cap, const string& src, const string& dest, map<string, map<string, int>>& adjacents, map<string, bool>& has_station) {
	ll ans = -1;

	map<string, map<int, ll>> dist;
	dist[src][cap] = 0;
	map<string, map<int, bool>> done;
	priority_queue<Node> que;
	que.emplace(src, cap, 0);

	while (!que.empty()) {
		Node node = que.top();
		que.pop();
		if (node.city == dest) {
			ans = dist[node.city][node.gas];
			break;
		}
		done[node.city][node.gas] = true;

		for (const auto& adjacent : adjacents[node.city]) {
			int adjacent_gas = node.gas - adjacent.second;
			if (adjacent_gas < 0) continue;
			if (has_station[adjacent.first]) adjacent_gas = cap;
			if (done[adjacent.first][adjacent_gas]) continue;
			ll adjacent_dist = node.dist + adjacent.second;

			bool dismiss = false;
			for (const auto& gas_and_dist : dist[adjacent.first]) {
				if (adjacent_gas <= gas_and_dist.first and adjacent_dist >= gas_and_dist.second) dismiss = true;
			}
			if (dismiss) continue;

			dist[adjacent.first][adjacent_gas] = adjacent_dist;
			que.emplace(adjacent.first, adjacent_gas, adjacent_dist);
		}
	}

	return ans;
}

bool solve() {
	int n, m, cap;
	cin >> n >> m >> cap;
	if (n == 0) return false;
	string src, dest;
	cin >> src >> dest;
	map<string, map<string, int>> adjacents;
	for (int i = 0; i < n; i++) {
		string c1, c2;
		int d;
		cin >> c1 >> c2 >> d;
		adjacents[c1][c2] = adjacents[c2][c1] = d;
	}
	map<string, bool> has_station;
	for (int i = 0; i < m; i++) {
		string s;
		cin >> s;
		has_station[s] = true;
	}

	cout << ShortestWay(cap * 10, src, dest, adjacents, has_station) << endl;

	return true;
}

int main(void) {
	while (solve());
	return 0;
}
accuracy: 1
time_ms: 6200
memory_kb: 104212
final_rank: 20

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

// g <- pair < v , cost > 
template < class T >
vector< T > dijkstra(vector<vector<pair<int, T>>> &graph, int s) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(graph.size(), INF);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> q;
    q.push({dist[s] = T(0), s});
    while(!q.empty()){
        auto [uc, ui] = q.top(); q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : graph[ui]) if(dist[vi] > uc + vc) 
            q.push({dist[vi] = uc + vc, vi});
    }
    return dist;
}

int solve(int N, int M, int cap) {
    cap *= 10;

    map<string, int> mp;
    int sz = 0;
    auto ID = [&](string s) {
        if(!mp.count(s)) mp[s] = sz++;
        return mp[s];
    };
    int src = [&] { string s = in(); return ID(s); }();
    int dst = [&] { string s = in(); return ID(s); }();
    vector<vector<pair<int,int>>> G(N + N);
    for(int i : rep(N)) {
        string s = in(), t = in(); int d = in();
        int u = ID(s), v = ID(t);
        G[u].push_back({v, d});
        G[v].push_back({u, d});
    }
    vector<bool> station(N + N, false);
    for(int i : rep(M)) {
        string s = in();
        station[ID(s)] = true;
    }

    const int INF = 1e9;
    vector dist(N + N, vector(cap + 1, INF));
    heap_min<tuple<int,int,int>> q;
    q.push({dist[src][cap] = 0, src, cap});
    while(not q.empty()) {
        auto [ud, ui, uc] = q.top(); q.pop();
        if(dist[ui][uc] < ud) continue;
        for(auto [vi, d] : G[ui]) {
            if(0 <= uc - d) {
                int vc = station[vi] ? cap : uc - d;
                if(chmin(dist[vi][vc], ud + d)) q.push({ud + d, vi, vc});
            }
        }
    }

    int ans = INF;
    for(int c = 0; c <= cap; c++) chmin(ans, dist[dst][c]);
    return ans < INF ? ans : -1;
}

int main() {
    while(true) {
        int N = in(), M = in(), cap = in();
        if(make_tuple(N, M, cap) == make_tuple(0, 0, 0)) return 0;
        print(solve(N, M, cap));
    }
}
accuracy: 1
time_ms: 1100
memory_kb: 77356
final_rank: 12

code_snippet: // #define _GLIBCXX_DEBUG
#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < int(n); i++)
#define per(i, n) for (int i = (n)-1; 0 <= i; i--)
#define rep2(i, l, r) for (int i = (l); i < int(r); i++)
#define per2(i, l, r) for (int i = (r)-1; int(l) <= i; i--)
#define each(e, v) for (auto& e : v)
#define MM << " " <<
#define pb push_back
#define eb emplace_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define sz(x) (int)x.size()
template <typename T> void print(const vector<T>& v, T x = 0) {
    int n = v.size();
    for (int i = 0; i < n; i++) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (v.empty()) cout << '\n';
}
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template <typename T> bool chmax(T& x, const T& y) {
    return (x < y) ? (x = y, true) : false;
}
template <typename T> bool chmin(T& x, const T& y) {
    return (x > y) ? (x = y, true) : false;
}
template <class T>
using minheap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T> using maxheap = std::priority_queue<T>;
template <typename T> int lb(const vector<T>& v, T x) {
    return lower_bound(begin(v), end(v), x) - begin(v);
}
template <typename T> int ub(const vector<T>& v, T x) {
    return upper_bound(begin(v), end(v), x) - begin(v);
}
template <typename T> void rearrange(vector<T>& v) {
    sort(begin(v), end(v));
    v.erase(unique(begin(v), end(v)), end(v));
}

// __int128_t gcd(__int128_t a, __int128_t b) {
//     if (a == 0)
//         return b;
//     if (b == 0)
//         return a;
//     __int128_t cnt = a % b;
//     while (cnt != 0) {
//         a = b;
//         b = cnt;
//         cnt = a % b;
//     }
//     return b;
// }

struct Union_Find_Tree {
    vector<int> data;
    const int n;
    int cnt;
 
    Union_Find_Tree(int n) : data(n, -1), n(n), cnt(n) {}
 
    int root(int x) {
        if (data[x] < 0) return x;
        return data[x] = root(data[x]);
    }
 
    int operator[](int i) { return root(i); }
 
    bool unite(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        if (data[x] > data[y]) swap(x, y);
        data[x] += data[y], data[y] = x;
        cnt--;
        return true;
    }
 
    int size(int x) { return -data[root(x)]; }
 
    int count() { return cnt; };
 
    bool same(int x, int y) { return root(x) == root(y); }
 
    void clear() {
        cnt = n;
        fill(begin(data), end(data), -1);
    }
};

template <int mod> struct Mod_Int {
    int x;

    Mod_Int() : x(0) {}

    Mod_Int(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    static int get_mod() { return mod; }

    Mod_Int& operator+=(const Mod_Int& p) {
        if ((x += p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int& operator-=(const Mod_Int& p) {
        if ((x += mod - p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int& operator*=(const Mod_Int& p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    Mod_Int& operator/=(const Mod_Int& p) {
        *this *= p.inverse();
        return *this;
    }

    Mod_Int& operator++() { return *this += Mod_Int(1); }

    Mod_Int operator++(int) {
        Mod_Int tmp = *this;
        ++*this;
        return tmp;
    }

    Mod_Int& operator--() { return *this -= Mod_Int(1); }

    Mod_Int operator--(int) {
        Mod_Int tmp = *this;
        --*this;
        return tmp;
    }

    Mod_Int operator-() const { return Mod_Int(-x); }

    Mod_Int operator+(const Mod_Int& p) const { return Mod_Int(*this) += p; }

    Mod_Int operator-(const Mod_Int& p) const { return Mod_Int(*this) -= p; }

    Mod_Int operator*(const Mod_Int& p) const { return Mod_Int(*this) *= p; }

    Mod_Int operator/(const Mod_Int& p) const { return Mod_Int(*this) /= p; }

    bool operator==(const Mod_Int& p) const { return x == p.x; }

    bool operator!=(const Mod_Int& p) const { return x != p.x; }

    Mod_Int inverse() const {
        assert(*this != Mod_Int(0));
        return pow(mod - 2);
    }

    Mod_Int pow(long long k) const {
        Mod_Int now = *this, ret = 1;
        for (; k > 0; k >>= 1, now *= now) {
            if (k & 1) ret *= now;
        }
        return ret;
    }

    friend ostream& operator<<(ostream& os, const Mod_Int& p) {
        return os << p.x;
    }

    friend istream& operator>>(istream& is, Mod_Int& p) {
        long long a;
        is >> a;
        p = Mod_Int<mod>(a);
        return is;
    }
};

ll mpow2(ll x, ll n, ll mod) {
    ll ans = 1;
    x %= mod;
    while (n != 0) {
        if (n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n = n >> 1;
    }
    ans %= mod;
    return ans;
}

template <typename T> T modinv(T a, const T& m) {
    T b = m, u = 1, v = 0;
    while (b > 0) {
        T t = a / b;
        swap(a -= t * b, b);
        swap(u -= t * v, v);
    }
    return u >= 0 ? u % m : (m - (-u) % m) % m;
}

ll divide_int(ll a, ll b) {
    if (b < 0) a = -a, b = -b;
    return (a >= 0 ? a / b : (a - b + 1) / b);
}

// const int MOD = 1000000007;
const int MOD = 998244353;
using mint = Mod_Int<MOD>;

// ----- library -------
// ----- library -------

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (1) {
        int m, k, c;
        cin >> m >> k >> c;
        c *= 10;
        if (!m)
            break;
        string sa, sb;
        cin >> sa >> sb;
        vector<string> su(m), sv(m), ss(k);
        vector<int> d(m);
        rep(i, m) cin >> su[i] >> sv[i] >> d[i];
        rep(i, k) cin >> ss[i];
        vector<string> ls{sa, sb};
        rep(i, m) ls.eb(su[i]), ls.eb(sv[i]);
        rep(i, k) ls.eb(ss[i]);
        rearrange(ls);
        int a, b;
        vector<int> u(m), v(m), s(k);
        a = lb(ls, sa), b = lb(ls, sb);
        rep(i, m) u[i] = lb(ls, su[i]), v[i] = lb(ls, sv[i]);
        rep(i, k) s[i] = lb(ls, ss[i]);
        int n = sz(ls);
        vector<vector<pii>> g(n);
        vector<int> f(n, 0);
        rep(i, m) g[u[i]].eb(v[i], d[i]), g[v[i]].eb(u[i], d[i]);
        rep(i, k) f[s[i]] = 1;
        minheap<pair<int, pii>> que;
        vector<vector<int>> mi(n, vector<int>(c + 1, 1e9));
        mi[a][c] = 0, que.emplace(0, pair(a, c));
        while (sz(que)) {
            auto [nd, nij] = que.top();
            que.pop();
            auto [ni, nj] = nij;
            if (mi[ni][nj] != nd)
                continue;
            for (auto [nv, cost] : g[ni]) {
                if (nj < cost)
                    continue;
                int rest = (f[nv] ? c : nj - cost);
                if (chmin(mi[nv][rest], nd + cost))
                    que.emplace(nd + cost, pair(nv, rest));
            }
        }
        int ans = 1e9;
        rep(j, c + 1) chmin(ans, mi[b][j]);
        cout << (ans < 1e8 ? ans : -1) << '\n';
    }
}
accuracy: 1
time_ms: 1010
memory_kb: 52020
final_rank: 10

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

const int INF = 1012345678;

struct edge {
	int to, cost;
};

struct state {
	int pos, rem, cost;
	bool operator<(const state& s) const {
		return cost > s.cost;
	}
};

int solve(int N, int M, int C, const string& src, const string& dst, const vector<string>& A, const vector<string>& B, const vector<int>& D, const vector<string>& S) {
	vector<string> cities;
	cities.push_back(src);
	cities.push_back(dst);
	cities.insert(cities.end(), A.begin(), A.end());
	cities.insert(cities.end(), B.begin(), B.end());
	cities.insert(cities.end(), S.begin(), S.end());
	sort(cities.begin(), cities.end());
	cities.erase(unique(cities.begin(), cities.end()), cities.end());
	int V = cities.size();
	vector<vector<edge> > G(V);
	for (int i = 0; i < N; i++) {
		int va = lower_bound(cities.begin(), cities.end(), A[i]) - cities.begin();
		int vb = lower_bound(cities.begin(), cities.end(), B[i]) - cities.begin();
		G[va].push_back(edge{vb, D[i]});
		G[vb].push_back(edge{va, D[i]});
	}
	int vs = lower_bound(cities.begin(), cities.end(), src) - cities.begin();
	int vg = lower_bound(cities.begin(), cities.end(), dst) - cities.begin();
	vector<bool> station(V, false);
	for (int i = 0; i < M; i++) {
		int pos = lower_bound(cities.begin(), cities.end(), S[i]) - cities.begin();
		station[pos] = true;
	}
	vector<vector<int> > dist(V, vector<int>(C + 1, INF));
	priority_queue<state> que;
	vector<vector<bool> > vis(V, vector<bool>(C + 1, false));
	dist[vs][C] = 0;
	que.push(state{vs, C, 0});
	while (!que.empty()) {
		state s = que.top();
		que.pop();
		if (!vis[s.pos][s.rem]) {
			vis[s.pos][s.rem] = true;
			for (edge e : G[s.pos]) {
				int nrem = s.rem - e.cost;
				if (nrem >= 0) {
					if (station[e.to]) {
						nrem = C;
					}
					if (dist[e.to][nrem] > s.cost + e.cost) {
						dist[e.to][nrem] = s.cost + e.cost;
						que.push(state{e.to, nrem, dist[e.to][nrem]});
					}
				}
			}
		}
	}
	int ans = *min_element(dist[vg].begin(), dist[vg].end());
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	while (true) {
		int N, M, C;
		cin >> N >> M >> C;
		if (N == 0 && M == 0 && C == 0) {
			break;
		}
		C *= 10;
		string src, dst;
		cin >> src >> dst;
		vector<string> A(N), B(N);
		vector<int> D(N);
		for (int i = 0; i < N; i++) {
			cin >> A[i] >> B[i] >> D[i];
		}
		vector<string> S(M);
		for (int i = 0; i < M; i++) {
			cin >> S[i];
		}
		int ans = solve(N, M, C, src, dst, A, B, D, S);
		cout << (ans != INF ? ans : -1) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 660
memory_kb: 54632
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
struct Edge {
    int from, to;
    T weight;
    Edge() = default;
    Edge(int to, T weight) : from(-1), to(to), weight(weight) {}
    Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};


template <typename T>
std::vector<T> dijkstra(const std::vector<std::vector<Edge<T>>>& G, int s) {
    std::vector<T> dist(G.size(), std::numeric_limits<T>::max());
    dist[s] = 0;
    using P = std::pair<T, int>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> pq;
    pq.emplace(0, s);

    while (!pq.empty()) {
        T d;
        int v;
        std::tie(d, v) = pq.top();
        pq.pop();
        if (dist[v] < d) continue;
        for (auto& e : G[v]) {
            if (dist[e.to] > d + e.weight) {
                dist[e.to] = d + e.weight;
                pq.emplace(dist[e.to], e.to);
            }
        }
    }

    return dist;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int N, M, cap;
        cin >> N >> M >> cap;
        if (N == 0) break;
        string src, dest;
        cin >> src >> dest;
        vector<vector<Edge<int>>> G;
        map<string, int> idx;
        rep(_,0,N) {
            string su, sv;
            int d;
            cin >> su >> sv >> d;
            int u, v;
            if (idx.count(su)) u = idx[su];
            else {
                u = idx.size();
                idx[su] = u;
                G.emplace_back();
            }
            if (idx.count(sv)) v = idx[sv];
            else {
                v = idx.size();
                idx[sv] = v;
                G.emplace_back();
            }
            G[u].push_back({v, d});
            G[v].push_back({u, d});
        }
        int V = G.size();
        if (!idx.count(src) || !idx.count(dest)) {
            cout << -1 << endl;
            continue;
        }
        vector<int> stations;
        rep(i,0,M) {
            string s;
            cin >> s;
            stations.push_back(idx[s]);
        }
        stations.push_back(idx[src]);
        stations.push_back(idx[dest]);
        vector<vector<Edge<int>>> G2(V);
        for (int s : stations) {
            auto dist = dijkstra(G, s);
            for (int t : stations) {
                if (dist[t] <= cap * 10) G2[s].push_back({t, dist[t]});
            }
        }
        auto dist = dijkstra(G2, idx[src]);
        int ans = dist[idx[dest]];
        cout << (ans < 1e9 ? ans : -1) << endl;
    }
}
accuracy: 1
time_ms: 280
memory_kb: 5496
final_rank: 3

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

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T> using V = vector<T>;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N, M, cap;
    while (cin >> N >> M >> cap, !(N == 0 and M == 0 and cap == 0)) {
        V<string> SS;
        string src, dst;
        cin >> src >> dst;
        SS.push_back(src);
        SS.push_back(dst);
        V<string> c1(N), c2(N);
        V<int> d(N);
        rep(i, N) {
            cin >> c1[i] >> c2[i] >> d[i];
            SS.push_back(c1[i]);
            SS.push_back(c2[i]);
        }
        V<string> S(M);
        rep(i, M) {
            cin >> S[i];
            SS.push_back(S[i]);
        }
        sort(SS.begin(), SS.end());
        SS.erase(unique(SS.begin(), SS.end()), SS.end());
        int NV = SS.size();
        V<V<pair<int, ll>>> G(NV);
        rep(i, N) {
            int a = lower_bound(SS.begin(), SS.end(), c1[i]) - SS.begin();
            int b = lower_bound(SS.begin(), SS.end(), c2[i]) - SS.begin();
            G[a].push_back({b, d[i]});
            G[b].push_back({a, d[i]});
        }
        V<int> gas(NV, 0);
        rep(i, M) {
            int a = lower_bound(SS.begin(), SS.end(), S[i]) - SS.begin();
            gas[a] = 1;
        }
        const ll INF = 1LL << 60;
        cap *= 10;
        V<V<ll>> dist(NV, V<ll>(cap + 1, INF));
        int s = lower_bound(SS.begin(), SS.end(), src) - SS.begin();
        int g = lower_bound(SS.begin(), SS.end(), dst) - SS.begin();
        dist[s][cap] = 0;
        priority_queue<tuple<ll, int, int>> que;
        que.push({0, s, cap});
        bool ok = false;
        while (!que.empty()) {
            auto [d, cv, ccap] = que.top();
            que.pop();
            d = -d;
            if (cv == g) {
                cout << d << '\n';
                ok = true;
                break;
            }
            if (dist[cv][ccap] != d) continue;
            if (gas[cv] and ccap < cap) {
                dist[cv][cap] = d;
                que.push({-d, cv, cap});
            }
            for (auto [nex, cost] : G[cv]) {
                if (ccap >= cost) {
                    if (dist[nex][ccap - cost] > d + cost) {
                        dist[nex][ccap - cost] = d + cost;
                        que.push({-(d + cost), nex, ccap - cost});
                    }
                }
            }
        }
        if (!ok) cout << -1 << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 1430
memory_kb: 97808
final_rank: 17

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

#ifdef _MSC_VER
#  include <intrin.h>
#else
#  include <x86intrin.h>
#endif

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

template <typename T, typename = void>
struct rec_value_type {
    using type = T;
};
template <typename T>
struct rec_value_type<T, std::void_t<typename T::value_type>> {
    using type = typename rec_value_type<typename T::value_type>::type;
};
template <typename T>
using rec_value_type_t = typename rec_value_type<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// __int128_t
std::ostream& operator<<(std::ostream& dest, __int128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}
// __uint128_t
std::ostream& operator<<(std::ostream& dest, __uint128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[value % 10];
            value /= 10;
        } while (value != 0);
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head& head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

__int128_t parse_i128(std::string& s) {
    __int128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    if (s[0] == '-') ret = -ret;
    return ret;
}
__uint128_t parse_u128(std::string& s) {
    __uint128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    return ret;
}
// __int128_t
std::istream& operator>>(std::istream& in, __int128_t& v) {
    std::string s;
    in >> s;
    v = parse_i128(s);
    return in;
}
// __uint128_t
std::istream& operator>>(std::istream& in, __uint128_t& v) {
    std::string s;
    in >> s;
    v = parse_u128(s);
    return in;
}
// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U>& a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    (std::cin >> ... >> args);
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u64(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> -1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable& iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T>& a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()) {
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T& x, const T& y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T& x, const T& y) {
    if (y <= x) return false;
    x = y;
    return true;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::string bin(T val, int bit_num = -1) {
    std::string res;
    if (bit_num >= 0) {
        for (int bit = bit_num; bit-- > 0;) res += '0' + ((val >> bit) & 1);
    } else {
        for (; val; val >>= 1) res += '0' + (val & 1);
        std::reverse(res.begin(), res.end());
    }
    return res;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_low_to_high(T val, T base = 10) {
    std::vector<T> res;
    for (; val; val /= base) res.push_back(val % base);
    if (res.empty()) res.push_back(T{ 0 });
    return res;
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_high_to_low(T val, T base = 10) {
    auto res = digits_low_to_high(val, base);
    std::reverse(res.begin(), res.end());
    return res;
}

template <typename T>
std::string join(const std::vector<T>& v, const std::string& sep, const std::string& end) {
    std::ostringstream ss;
    for (auto it = v.begin(); it != v.end();) {
        ss << *it;
        if (++it != v.end()) ss << sep;
    }
    ss << end;
    return ss.str();
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_{};

// ! code from here

#include <algorithm>
#include <cassert>
#include <vector>

namespace suisen {
template <typename T>
class CoordinateCompressorBuilder {
    public:
        struct Compressor {
            public:
                static constexpr int absent = -1;

                // default constructor
                Compressor() : _xs(std::vector<T>{}) {}
                // Construct from strictly sorted vector
                Compressor(const std::vector<T> &xs) : _xs(xs) {
                    assert(is_strictly_sorted(xs));
                }

                // Return the number of distinct keys.
                int size() const {
                    return _xs.size();
                }
                // Check if the element is registered.
                bool has_key(const T &e) const {
                    return std::binary_search(_xs.begin(), _xs.end(), e);
                }
                // Compress the element. if not registered, returns `default_value`. (default: Compressor::absent)
                int comp(const T &e, int default_value = absent) const {
                    const int res = min_geq_index(e);
                    return res != size() and _xs[res] == e ? res : default_value;
                }
                // Restore the element from the index.
                T decomp(const int compressed_index) const {
                    return _xs[compressed_index];
                }
                // Compress the element. Equivalent to call `comp(e)`
                int operator[](const T &e) const {
                    return comp(e);
                }
                // Return the minimum registered value greater than `e`. if not exists, return `default_value`.
                T min_gt(const T &e, const T &default_value) const {
                    auto it = std::upper_bound(_xs.begin(), _xs.end(), e);
                    return it == _xs.end() ? default_value : *it;
                }
                // Return the minimum registered value greater than or equal to `e`. if not exists, return `default_value`.
                T min_geq(const T &e, const T &default_value) const {
                    auto it = std::lower_bound(_xs.begin(), _xs.end(), e);
                    return it == _xs.end() ? default_value : *it;
                }
                // Return the maximum registered value less than `e`. if not exists, return `default_value`
                T max_lt(const T &e, const T &default_value) const {
                    auto it = std::upper_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>());
                    return it == _xs.rend() ? default_value : *it;
                }
                // Return the maximum registered value less than or equal to `e`. if not exists, return `default_value`
                T max_leq(const T &e, const T &default_value) const {
                    auto it = std::lower_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>());
                    return it == _xs.rend() ? default_value : *it;
                }
                // Return the compressed index of the minimum registered value greater than `e`. if not exists, return `compressor.size()`.
                int min_gt_index(const T &e) const {
                    return std::upper_bound(_xs.begin(), _xs.end(), e) - _xs.begin();
                }
                // Return the compressed index of the minimum registered value greater than or equal to `e`. if not exists, return `compressor.size()`.
                int min_geq_index(const T &e) const {
                    return std::lower_bound(_xs.begin(), _xs.end(), e) - _xs.begin();
                }
                // Return the compressed index of the maximum registered value less than `e`. if not exists, return -1.
                int max_lt_index(const T &e) const {
                    return int(_xs.rend() - std::upper_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>())) - 1;
                }
                // Return the compressed index of the maximum registered value less than or equal to `e`. if not exists, return -1.
                int max_leq_index(const T &e) const {
                    return int(_xs.rend() - std::lower_bound(_xs.rbegin(), _xs.rend(), e, std::greater<T>())) - 1;
                }
            private:
                std::vector<T> _xs;
                static bool is_strictly_sorted(const std::vector<T> &v) {
                    return std::adjacent_find(v.begin(), v.end(), std::greater_equal<T>()) == v.end();
                }
        };
        CoordinateCompressorBuilder() : _xs(std::vector<T>{}) {}
        explicit CoordinateCompressorBuilder(const std::vector<T> &xs) : _xs(xs) {}
        explicit CoordinateCompressorBuilder(std::vector<T> &&xs) : _xs(std::move(xs)) {}
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        CoordinateCompressorBuilder(const int n, Gen generator) {
            reserve(n);
            for (int i = 0; i < n; ++i) push(generator(i));
        }
        // Attempt to preallocate enough memory for specified number of elements.
        void reserve(int n) {
            _xs.reserve(n);
        }
        // Add data.
        void push(const T &first) {
            _xs.push_back(first);
        }
        // Add data.
        void push(T &&first) {
            _xs.push_back(std::move(first));
        }
        // Add data in the range of [first, last). 
        template <typename Iterator>
        auto push(const Iterator &first, const Iterator &last) -> decltype(std::vector<T>{}.push_back(*first), void()) {
            for (auto it = first; it != last; ++it) _xs.push_back(*it);
        }
        // Add all data in the container. Equivalent to `push(iterable.begin(), iterable.end())`.
        template <typename Iterable>
        auto push(const Iterable &iterable) -> decltype(std::vector<T>{}.push_back(*iterable.begin()), void()) {
            push(iterable.begin(), iterable.end());
        }
        // Add data.
        template <typename ...Args>
        void emplace(Args &&...args) {
            _xs.emplace_back(std::forward<Args>(args)...);
        }
        // Build compressor.
        auto build() {
            std::sort(_xs.begin(), _xs.end()), _xs.erase(std::unique(_xs.begin(), _xs.end()), _xs.end());
            return Compressor {_xs};
        }
        // Build compressor from vector.
        static auto build(const std::vector<T> &xs) {
            return CoordinateCompressorBuilder(xs).build();
        }
        // Build compressor from vector.
        static auto build(std::vector<T> &&xs) {
            return CoordinateCompressorBuilder(std::move(xs)).build();
        }
        // Build compressor from generator.
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        static auto build(const int n, Gen generator) {
            return CoordinateCompressorBuilder<T>(n, generator).build();
        }
    private:
        std::vector<T> _xs;
};

} // namespace suisen

long long solve(int n, int c, int s, int t, vector<tuple<int, int, int>> edges, vector<int> st) {
    vector<int8_t> gs(n, false);
    for (auto e : st) {
        gs[e] = true;
    }

    vector<vector<pair<int, int>>> g(n);
    for (auto [u, v, w] : edges) {
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    }

    vector d(n, vector<long long>(c + 1, numeric_limits<long long>::max()));
    pq_greater<tuple<long long, int, int>> pq;
    pq.emplace(d[s][c] = 0, s, c);
    while (pq.size()) {
        auto [dvx, v, x] = pq.top();
        pq.pop();
        if (dvx != d[v][x]) continue;
        for (auto [nv, w] : g[v]) if (w <= x) {
            int nx = gs[nv] ? c : x - w;
            if (chmin(d[nv][nx], dvx + w)) {
                pq.emplace(d[nv][nx], nv, nx);
            }
        }
    }

    long long ans = *min_element(all(d[t]));
    if (ans == numeric_limits<long long>::max()) return -1;
    return ans;
}

int main() {
    while (true) {
        input(int, n, m, c);
        if (n == 0 and m == 0 and c == 0) break;;

        c *= 10;
        input(string, s, t);
        vector<tuple<string, string, int>> edges(n);
        read(edges);
        vector<string> st(m);
        read(st);

        CoordinateCompressorBuilder<string> builder;
        builder.push(s);
        builder.push(t);

        for (auto& [u, v, w] : edges) {
            builder.push(u);
            builder.push(v);
        }
        for (auto& x : st) {
            builder.push(x);
        }
        auto cmp = builder.build();

        int si = cmp[s], ti = cmp[t];
        vector<tuple<int, int, int>> es;
        for (auto& [u, v, w] : edges) {
            es.emplace_back(cmp[u], cmp[v], w);
        }
        vector<int> sts;
        for (auto& x : st) {
            sts.push_back(cmp[x]);
        }
        print(solve(cmp.size(), c, si, ti, es, sts));
    }

    return 0;
}
accuracy: 1
time_ms: 1200
memory_kb: 98244
final_rank: 15

code_snippet: #include <stdio.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#define INF 1012345678
using namespace std;

char buff1[32], buff2[32];
unordered_map<string, vector<pair<string, int>>> ed;
vector<pair<int, int>> edn[6144], edn2[6144];
unordered_map<string, int> nodenm;
int distn[6144], visn[6144];
unordered_set<string> city, lpg;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;

void dijk(int src, int n, int m, int cap) {
    int node, d;
    for (int i = 1; i <= n; i++) {
        distn[i] = cap + 1;
        visn[i] = 0;
    }
    
    while (pq.size()) pq.pop();
    pq.push({ 0, src });
    while (pq.size()) {
        node = pq.top().second;
        d = pq.top().first;
        pq.pop();
        if (visn[node]) continue;
        else visn[node] = 1;
        for (auto& i : edn[node]) {
            if (d + i.second < distn[i.first]) {
                distn[i.first] = d + i.second;
                pq.push({ distn[i.first], i.first });
            }
        }
    }

    for (int i = 1; i <= m; i++) {
        if (distn[i] <= cap) {
            edn2[src].push_back({ i, distn[i] });
        }
    }
}

int dijk2(int src, int dest, int n) {
    int node;
    int d;
    for (int i = 1; i <= n; i++) {
        distn[i] = INF;
        visn[i] = 0;
    }

    while (pq.size()) pq.pop();
    pq.push({ 0, src });
    while (pq.size()) {
        node = pq.top().second;
        d = pq.top().first;
        pq.pop();
        if (node == dest) return d;
        if (visn[node]) continue;
        else visn[node] = 1;
        for (auto& i : edn2[node]) {
            if (d + i.second < distn[i.first]) {
                distn[i.first] = d + i.second;
                pq.push({ distn[i.first], i.first });
            }
        }
    }

    return -1;
}

int main(void) {
    string src, dest;
    int n, m, cap, x;
    while (1) {
        scanf("%d %d %d", &n, &m, &cap);
        if (n == 0 && m == 0 && cap == 0) break;
        else cap *= 10;
        scanf("%s %s", buff1, buff2);
        src = buff1, dest = buff2;
        for (int i = 0; i < n; i++) {
            scanf("%s %s %d", buff1, buff2, &x);
            if (ed.find(buff1) == ed.end()) ed.insert({ buff1, {{buff2, x}} });
            else ed[buff1].push_back({ buff2, x });
            if (ed.find(buff2) == ed.end()) ed.insert({ buff2, {{buff1, x}} });
            else ed[buff2].push_back({ buff1, x });
            if (city.find(buff1) == city.end()) city.insert(buff1);
            if (city.find(buff2) == city.end()) city.insert(buff2);
        }
        for (int i = 0; i < m; i++) {
            scanf("%s", buff1);
            lpg.insert(buff1);
        }
        lpg.insert(src);
        lpg.insert(dest);
        nodenm.insert({ src, 1 });
        nodenm.insert({ dest, 2 });
        m = 2;
        for (auto& i : lpg) {
            if (i == src || i == dest) continue;
            nodenm.insert({ i, ++m });
        }
        n = m;
        for (auto& i : city) {
            if (lpg.find(i) != lpg.end()) continue;
            nodenm.insert({ i, ++n });
        }
        for (auto& i : ed) {
            for (auto& j : i.second) {
                edn[nodenm[i.first]].push_back({nodenm[j.first], j.second});
            }
        }


        for (int i = 1; i <= m; i++) {
            dijk(i, n, m, cap);
        }
        printf("%d\n", dijk2(1, 2, m));


        city.clear();
        lpg.clear();
        ed.clear();
        for (int i = 1; i <= n; i++) {
            edn[i].clear();
            edn2[i].clear();
        }
        nodenm.clear();
    }
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 6128
final_rank: 2

code_snippet: #include <stdio.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#define INF 1012345678
using namespace std;

char buff1[32], buff2[32];
unordered_map<string, vector<pair<string, int>>> ed, ed2;
unordered_map<string, int> dist;
unordered_set<string> city, lpg, vis;
priority_queue<pair<int, string>, vector<pair<int, string>>, greater<>> pq;

void dijk(string src, string node, int cap) {
    int d;
    dist.clear();
    vis.clear();
    for (auto& i : city) dist.insert({ i, cap + 1 });
    pq.push({ 0, src });
    while (pq.size()) {
        node = pq.top().second;
        d = pq.top().first;
        pq.pop();
        if (vis.find(node) != vis.end()) continue;
        else vis.insert(node);
        for (auto& i : ed[node]) {
            if (d + i.second < dist[i.first]) {
                dist[i.first] = d + i.second;
                pq.push({ dist[i.first], i.first });
            }
        }
    }

    for (auto& i : dist) {
        if (i.second <= cap && lpg.find(i.first) != lpg.end()) {
            if (ed2.find(src) == ed2.end()) ed2.insert({ src, {{i.first, i.second}} });
            else ed2[src].push_back({ i.first, i.second });
        }
    }
}

int dijk2(string src, string dest) {
    string node;
    int d;
    dist.clear();
    vis.clear();
    for (auto& i : lpg) dist.insert({ i, INF });
    pq.push({ 0, src });
    while (pq.size()) {
        node = pq.top().second;
        d = pq.top().first;
        pq.pop();
        if (node == dest) return d;
        if (vis.find(node) != vis.end()) continue;
        else vis.insert(node);
        for (auto& i : ed2[node]) {
            if (d + i.second < dist[i.first]) {
                dist[i.first] = d + i.second;
                pq.push({ dist[i.first], i.first });
            }
        }
    }

    return -1;
}

int main(void) {
    string src, dest;
    int n, m, cap, x;
    while (1) {
        scanf("%d %d %d", &n, &m, &cap);
        if (n == 0 && m == 0 && cap == 0) break;
        else cap *= 10;
        scanf("%s %s", buff1, buff2);
        src = buff1, dest = buff2;
        for (int i = 0; i < n; i++) {
            scanf("%s %s %d", buff1, buff2, &x);
            if (ed.find(buff1) == ed.end()) ed.insert({ buff1, {{buff2, x}} });
            else ed[buff1].push_back({ buff2, x });
            if (ed.find(buff2) == ed.end()) ed.insert({ buff2, {{buff1, x}} });
            else ed[buff2].push_back({ buff1, x });
            if (city.find(buff1) == city.end()) city.insert(buff1);
            if (city.find(buff2) == city.end()) city.insert(buff2);
        }
        for (int i = 0; i < m; i++) {
            scanf("%s", buff1);
            lpg.insert(buff1);
        }
        lpg.insert(src);
        lpg.insert(dest);
        for (auto& i : lpg) {
            dijk(i, i, cap);
        }
        printf("%d\n", dijk2(src, dest));


        city.clear();
        lpg.clear();
        dist.clear();
        vis.clear();
        ed.clear();
        ed2.clear();
    }
    return 0;
}
accuracy: 1
time_ms: 1790
memory_kb: 9008
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int inf = 1 << 30;

struct abc{
    string a;
    string b;
    int c;
};

struct nc{
    int npos;
    int c;
};

struct HQ{
    int d;
    int pos;
    int cap;
    
    bool operator<(const HQ& right) const{
        return d > right.d;
    }
};

int main(void){
    int n, m, cap;
    while(1){
        cin >> n >> m >> cap;
        if(n == 0) break;
        string s, g;
        cin >> s >> g;
        set<string> city;
        city.insert(s);
        city.insert(g);
        vector<abc> E(n);
        for(int i = 0; i < n; i++){
            cin >> E[i].a >> E[i].b >> E[i].c;
            city.insert(E[i].a);
            city.insert(E[i].b);
        }
        map<string, int> mp;
        int x = 0;
        for(auto c: city){
            mp[c] = x;
            x++;
        }
        set<int> se;
        for(int i = 0; i < m; i++){
            string tmp;
            cin >> tmp;
            se.insert(mp[tmp]);
        }
        int ss = mp[s];
        int gg = mp[g];
        se.insert(gg);
        int l = city.size();
        vector<vector<nc>> edges(l, vector<nc>());
        for(auto tmp: E){
            edges[mp[tmp.a]].push_back({mp[tmp.b], tmp.c});
            edges[mp[tmp.b]].push_back({mp[tmp.a], tmp.c});
        }
        cap *= 10;
        vector<vector<int>> dist(l, vector<int>(cap + 1, inf));
        dist[ss][cap] = 0;
        priority_queue<HQ> hq;
        hq.push({0, ss, cap});
        int d, pos, cc, npos, c, nc, nd;
        while(!hq.empty()){
            auto tmp = hq.top();
            d = tmp.d;
            pos = tmp.pos;
            cc = tmp.cap;
            hq.pop();
            if(se.count(pos) && cc != cap){
                if(dist[pos][cap] > d){
                    dist[pos][cap] = d;
                    hq.push({d, pos, cap});
                }
                continue;
            }
            
            for(auto tmp2: edges[pos]){
                npos = tmp2.npos;
                c = tmp2.c;
                if(c > cc) continue;
                nc = cc - c;
                nd = d + c;
                if(dist[npos][nc] > nd){
                    dist[npos][nc] = nd;
                    hq.push({nd, npos, nc});
                }
            }
        }
        if(dist[gg][cap] == inf) cout << "-1\n";
        else cout << dist[gg][cap] << "\n";
    }
    
}
accuracy: 1
time_ms: 960
memory_kb: 52472
final_rank: 9