#include "testlib.h"
#include <cassert>
#include <queue>

typedef long long ll;
typedef long double ld;
using std::vector;
using std::pair;
using std::string;
using std::set;
using std::map;
using std::max;
using std::numeric_limits;
using std::priority_queue;
using std::greater;
using std::to_string;
using std::swap;
typedef pair<ld,ll> kaugusJaIndeks;

/**
Klass, mis hoiab kõiki sisendi raadiusega ringe, kusjuures Delta ja Kaarsild on raadiusega 0
*/
struct Ring {
    ll x,y,r;
    string nimi;
    Ring(ll x,ll y,ll r,string nimi):x(x),y(y),r(r),nimi(nimi){}
};

/**
Funktsioon kahe ringi vahelise kauguse arvutamiseks
*/
ld ringideKaugus(const Ring& A, const Ring& B){
    ld dx = A.x - B.x;
    ld dy = A.y - B.y;
    ld d = sqrt(dx*dx + dy*dy) - (A.r + B.r);
    return max(d, (ld)0);
}

/**
Lahendusfunktsioon põhineb Dijkstra algoritmil
*/
ld luhimTee(const vector<Ring>& punktid,int algus,int lopp){
    int N=punktid.size();

    vector<ld>kaugusAlgusest(N,numeric_limits<ld>::max());//Hoiame meeles iga punkti jooksvat kaugust alguspunktist
    kaugusAlgusest[algus]=0;//alguspunkti kaugus endast on 0

    vector<int>eelmineTippTeekonnal(N,-1);
    //Lõpus lühima teekonna väljastamiseks hoiame jooksvalt meeles, mis punktist me igasse punkti liikusime,
    //oluline on just vahetult eelnev punkt

    priority_queue<kaugusJaIndeks,vector<kaugusJaIndeks>,greater<kaugusJaIndeks>>pq;
    //Dijkstra algoritmi töövoogu hoiame priority_queue's, mis tagastab meile igal sammul alguspunktile lähima punkti
    pq.push({0,algus});//Algtipu kohta on kohe teada, et ta on kaugusel 0

    while(!pq.empty()){
        auto vahim=pq.top();pq.pop();//leiame alguspunktile lähima punkti
        int U=vahim.second;//see on tema indeks punktide vektoris

        if(vahim.first != kaugusAlgusest[U])//Selleks hetkeks on tipu kaugus algusest juba lõplikult kindel,
                                            //kuid queues võib olla ka suurema kaugusega selle punkti esitusi mida ignoreerime
            continue;

        for(int V=0;V<N;V++){//Vaatame läbi kõik ülejäänud punktid
            ld kaugusUV = ringideKaugus(punktid[U],punktid[V]);//Kui kaugel on punktid U ja V üksteisest

            if(kaugusAlgusest[U]+kaugusUV<kaugusAlgusest[V]){//Kas teekond algusest puntki V saaks lühem,
                                                             //kui läheksime lühimat teed mööda algusest puntki U ja sealt otse punkti V
                kaugusAlgusest[V]=kaugusAlgusest[U]+kaugusUV;//Jah, uuendame kaugust
                eelmineTippTeekonnal[V]=U;                   //Tulime tipust U
                pq.push({kaugusAlgusest[V],V});              //Lisame uuenduse töövoogu
            }
        }
    }

    return kaugusAlgusest[lopp];
}

struct DSU{
    vector<int>p,sz;
    DSU(int n){
        p.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++)p[i]=i;
    }
    DSU(const vector<Ring>&ringid): DSU(ringid.size()) {
        const int N=ringid.size();
        for(int i=0;i<N;i++){
            for(int j=0;j<i;j++){
                if(same_comp(i,j))continue;
                ld kaugus = ringideKaugus(ringid[i],ringid[j]);
                if(kaugus==0){
                    unite(i,j);
                }
            }
        }
    }

    int F(int u){
        if(u==p[u])return u;
        return p[u]=F(p[u]);
    }

    void unite(int u,int v){
        u=F(u);
        v=F(v);
        if(u==v)return;
        if(sz[u]>sz[v])swap(u,v);
        if(sz[u]==sz[v])sz[v]++;
        p[u]=v;
    }
    bool same_comp(int u,int v){
        return F(u)==F(v);
    }
};

int S6neIndeksiks(const string& s6ne,int N){
    if(s6ne=="Kaarsild"){
        return 0;
    }
    if(s6ne=="Delta"){
        return 1;
    }
    InStream tmp(ouf, s6ne);
    int i = tmp.readInt(1, N);
    tmp.readEof();
    return i+1;
}
string indeksS6neks(int i){
    if(i==0){
        return "Kaarsild";
    }
    if(i==1){
        return "Delta";
    }
    return to_string(i-1);
}

int main (int argc, char **argv) {
  if (argc < 3) {
    std::cerr << "usage: <input-file> <output-file>" << std::endl;
    return 1;
  } else if (argc == 3) {
    // this checker doesn't use the answer file
    // shortcut
    char *nargv [4] = {argv[0], argv[1], argv[2], argv[2]};
    registerTestlibCmd(4, nargv);
  } else {
    registerTestlibCmd(argc, argv);
  }

    vector<Ring>ringid;//Salvestame kõik sisend punktid ühte vektorisse

    ll x,y;
    x = inf.readInt();
    y = inf.readInt();
    inf.readEoln();
    ringid.push_back(Ring(x,y,0,"Kaarsild"));//Kaarsild ja Delta on meie vaates raadiusega 0 ringid
    x = inf.readInt();
    y = inf.readInt();
    inf.readEoln();
    ringid.push_back(Ring(x,y,0,"Delta"));//Lisame mõlemad vektori algussse

  int N = inf.readInt();
  inf.readEoln();

  for(int i=1;i<=N;i++){//Seejärel loeme sisendist puuvõrad ehk ülejäänud ringid
        ll x,y,r;
        x = inf.readInt();
        y = inf.readInt();
        r = inf.readInt();
        inf.readEoln();
        ringid.push_back(Ring(x,y,r,to_string(i)));
    }

  int M = ouf.readInt();
  ouf.readEoln();

  DSU tasutaYhendused(ringid);
  ld kontrollitavaKoguKaugus=0;
  int kontrollitavaViimane=0;//Algus on kaarsild
  for(int i=1;i<=M;i++){
    string A = ouf.readToken();
    string L = ouf.readToken();
    ouf.readEoln();

    int a=S6neIndeksiks(A,N);
    int l=S6neIndeksiks(L,N);

    if(!tasutaYhendused.same_comp(kontrollitavaViimane,a)){
        quit(_wa, "Walking in the rain from " + indeksS6neks(kontrollitavaViimane) + " to " + indeksS6neks(a));
    }
    kontrollitavaKoguKaugus+=ringideKaugus(ringid[a],ringid[l]);
    kontrollitavaViimane=l;
  }
  if(!tasutaYhendused.same_comp(kontrollitavaViimane,1)){
    quit(_wa, "Walking in the rain from " + indeksS6neks(kontrollitavaViimane) + " to " + indeksS6neks(1));
  }

  ld p2risVastus=luhimTee(ringid,0,1);
  if (!doubleCompare(p2risVastus, kontrollitavaKoguKaugus, 1e-6)) {
    quitf(_wa, "Expected total distance %.10f, got %.10f", (double)p2risVastus, (double)kontrollitavaKoguKaugus);
  }
  quitf(_ok, "OK");
}
