using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace idos
{
class Program
{
class stanica
{
public string meno;
public int kod;
public bool hotovy; //ci je cesta do daneho vrcholu definitivne najkratsia
public int cas; //cas za ktory sa do nej vieme dostat
public stanica pred; //predchodca na ceste do stanice
public hrana ktorouSmePrisli;
public List<hrana> susedia;
public stanica(string meno, int kod)
{
this.meno = meno;
this.kod = kod;
this.hotovy = false;
this.cas = int.MaxValue;
this.pred = null;
this.ktorouSmePrisli = null;
this.susedia = new List<hrana>();
}
}
class hrana
{
public int index; //kod susedneho vrcholu
public string vlak;
public int dlzka; //dlzka cesty v minutach
public int odchod; //v akom case odchadza
public hrana(int i, string v, int d, int o)
{
this.index = i;
this.vlak = v;
this.dlzka = d;
this.odchod = o;
}
}
static bool ziskajIndex(string s, ref int i)
{
foreach (stanica x in graf)
{
if (x.meno.ToLower() == s.ToLower())
{
i = x.kod;
return true;
}
}
return false;
}
static void nacitajGraf(string subor)
{
StreamReader r = new StreamReader(subor);
int pocetStanic = Convert.ToInt32(r.ReadLine());
graf = new List<stanica>();
for (int i = 0; i < pocetStanic; i++)
{
string menoStanice = r.ReadLine();
graf.Add(new stanica(menoStanice, i));
}
int pocetVlakov = Convert.ToInt32(r.ReadLine());
for (int i = 0; i < pocetVlakov; i++)
{
string menoVlaku = r.ReadLine();
char[] oddelovace = { ' ' };
string[] draha = (r.ReadLine()).Split(oddelovace, StringSplitOptions.RemoveEmptyEntries);
int predchodca = Convert.ToInt32(draha[0]);
int vCase = Convert.ToInt32(draha[1]);
for (int j = 2; j < draha.Length; j = j + 2)
{
int indexStanice = Convert.ToInt32(draha[j]);
int prichodVcase = Convert.ToInt32(draha[j + 1]);
//dlzka cesty je rozdiel medzi prichodom do predchodcu a prichodom do nasledovnika
graf[predchodca].susedia.Add(new hrana(indexStanice, menoVlaku, prichodVcase - vCase, vCase));
predchodca = indexStanice;
vCase = prichodVcase;
}
}
}
static bool najdiCestu(int start, int ciel, int cas)
{
foreach (hrana x in graf[start].susedia)
{
if (!graf[x.index].hotovy && //ak stanica este neni definitivna
graf[start].cas <= x.odchod && //ak vlak do stanice odchadza az ked sme na stanici aj my
graf[x.index].cas > x.odchod + x.dlzka) //ak je aktualny cas vacsi ako to co stravime cakanim a samotnou cestou...
//ak cesta do vrcholu este nie je definitivna
// a hranou x sa do vrcholu dostaneme v lepsom
//case v akom sme sa dokazali doteteraz
//tak zmenime udaje
{
graf[x.index].cas = x.odchod + x.dlzka;
graf[x.index].pred = graf[start];
graf[x.index].ktorouSmePrisli = x;
}
}
int minCas = int.MaxValue;
stanica taKtoruUzavreme = null;
foreach (stanica s in graf)
{
if (!s.hotovy && s.cas < minCas)
{
taKtoruUzavreme = s;
minCas = s.cas;
}
}
if (taKtoruUzavreme != null)
{
taKtoruUzavreme.hotovy = true;
if (taKtoruUzavreme.kod != ciel)
{
if (najdiCestu(taKtoruUzavreme.kod, ciel, taKtoruUzavreme.cas))
{
return true;
}
}
else return true;
}
return false;
}
static void vynulujGraf()
{
foreach (stanica x in graf)
{
x.cas = int.MaxValue;
x.pred = null;
x.ktorouSmePrisli = null;
x.hotovy = false;
}
}
static void zrekapitulujCestu(Stack<stanica> z)
{
stanica vrch = z.Peek();
if (vrch.pred != null)
{
z.Push(vrch.pred);
zrekapitulujCestu(z);
}
else
{
while (z.Count != 0)
{
stanica p = z.Pop();
stanica nasledovnik = z.Pop();
while (z.Count != 0 && z.Peek().ktorouSmePrisli.vlak == nasledovnik.ktorouSmePrisli.vlak)
{
nasledovnik = z.Pop();
}
if (z.Count != 0) z.Push(nasledovnik);
Console.WriteLine("o {0} ideme z {1} vlakom {2} do {3} a dorazime o {4}",
nasledovnik.ktorouSmePrisli.odchod,
p.meno,
nasledovnik.ktorouSmePrisli.vlak,
nasledovnik.meno,
nasledovnik.cas);
}
}
}
static List<stanica> graf;
static void Main(string[] args)
{
nacitajGraf(args[0]);
string prikaz = Console.ReadLine();
while (prikaz != "exit")
{
char[] oddelovace = { '\t', ' ' };
string[] rozdeleny = prikaz.Split(oddelovace, StringSplitOptions.RemoveEmptyEntries);
int start = 0;
int ciel = 0;
if (ziskajIndex(rozdeleny[0], ref start) &&
ziskajIndex(rozdeleny[1], ref ciel))
{
int cas = Convert.ToInt32(rozdeleny[2]);
//uzavrieme startovaci vrchol
graf[start].cas = cas;
graf[start].pred = null;
graf[start].hotovy = true;
if (najdiCestu(start, ciel, cas))
{
Stack<stanica> zasobnik = new Stack<stanica>();
zasobnik.Push(graf[ciel]);
zrekapitulujCestu(zasobnik);
vynulujGraf();
}
else
{
Console.WriteLine("cesta neexistuje");
vynulujGraf();
}
}
else Console.WriteLine("neplatny prikaz");
prikaz = Console.ReadLine();
}
}
}
}