#include <bits/stdc++.h>
using namespace std;
int n,m,k,Ds;
struct node{
int v,dist;
};
map<string,int> mp;
vector<node> G[1010];
//n:house num
//m:候选 气站 num
//k:路数量
//Ds:气站最大服务范围
int dist[1010],visited[1010];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > heap;
int this_min_dis;
double min_dis=-1;
double min_ave=DBL_MAX,this_ave=DBL_MAX;
int this_sum=0;
int min_id=INT_MAX;
bool dijkstra(int root){
fill(dist,dist+1010,INT_MAX);
fill(visited,visited+1010,0);
dist[root]=0;
heap.push(make_pair(0,root));
while(!heap.empty()){
int tmpId=heap.top().second;
int tmpDs=heap.top().first;
heap.pop();
if(visited[tmpId]) continue;
visited[tmpId]=1;
for(int i=0;i<G[tmpId].size();i++){
int kid=G[tmpId][i].v;
int kds=G[tmpId][i].dist;
if(visited[kid]==0){
if(dist[kid]>tmpDs+kds){
dist[kid]=tmpDs+kds;
heap.push(make_pair(dist[kid],kid));
}
}
}
}
//是否有不可到达的房子
int flag=1;
this_sum=0,this_min_dis=INT_MAX;
for(int i=1;i<=n;i++){
if(dist[i]>Ds){
flag=0;
break;
}
if(dist[i]<this_min_dis) this_min_dis=dist[i];
this_sum+=dist[i];
}
if(flag==0) return false;
this_ave=1.0*this_sum/n;
if(this_min_dis>min_dis){
min_ave=this_ave;
min_id=root-n;
min_dis=this_min_dis;
}else if(this_min_dis==min_dis && this_ave<min_ave){
min_ave=this_ave;
min_id=root-n;
}else if(this_min_dis==min_dis && this_ave<min_ave && min_id+n>root){
min_id=root-n;
}
return true;
}
int main(){
cin>>n>>m>>k>>Ds;
string st1,st2;
int t1,t2,tdist;
for(int i=1;i<=k;i++){
cin>>st1>>st2>>tdist;
if(st1[0]=='G'){
t1 = st1[1] - '0' + n;
mp[st1]=t1;
}
else t1=stoi(st1);
if(st2[0]=='G') {
t2 = st2[1] - '0' + n;
mp[st2]=t2;
}
else t2=stoi(st2);
G[t1].push_back(node{t2,tdist});
G[t2].push_back(node{t1,tdist});
}
int flag=0;
for(int i=0;i<m;i++){
if(dijkstra(n+i+1)) flag=1;
}
if(flag==0) cout<<"No Solution";
else
printf("G%d\n%.1f %.1f",min_id,min_dis,min_ave);
return 0;
}