#include #include #include using namespace std; struct hrana { int z, d; hrana(int _z, int _d) { z = _z; d = _d; } }; struct krizovatka { vector dovnitr, ven; // Jednosměrné ulice do a z křižovatky. vector obousmerne; // Obousměrné ulice sousedící s křižovatkou. int prvni_nepouzita; // První ulice do křižovatky, která ještě není v procházce. bool navstivena; // Značka pro prohledávání do hloubky. krizovatka() { prvni_nepouzita = 0; navstivena = false; } }; static krizovatka *graf; // Průchodem do hloubky určí počet ulic dosažitelných z křižovatky Z // bez ohledu na jejich směr (každá ulice je počítána dvakrát, jednou // za každý její konec). static int pocet_dostupnych(int z) { vector::iterator i; vector::iterator j; int pocet = 0; if (graf[z].navstivena) return 0; graf[z].navstivena = true; vector sousedi; for (i = graf[z].dovnitr.begin(); i != graf[z].dovnitr.end(); ++i) sousedi.push_back((*i)->z); for (i = graf[z].ven.begin(); i != graf[z].ven.end(); ++i) sousedi.push_back((*i)->d); for (j = graf[z].obousmerne.begin(); j != graf[z].obousmerne.end(); ++j) sousedi.push_back(*j); for (j = sousedi.begin(); j != sousedi.end(); j++) pocet += 1 + pocet_dostupnych(*j); return pocet; } // Přidá do grafu jednosměrnou hranu z křižovatky F do křižovatky T. static void pridej_jednosmernou_hranu(int f, int t) { hrana *h = new hrana(f, t); graf[f].ven.push_back(h); graf[t].dovnitr.push_back(h); } // Smaže z grafu obousměrnou hranu mezi křižovatkami F a T. static void smaz_obousmernou_hranu(int f, int t) { vector::iterator i; for (i = graf[f].obousmerne.begin(); i != graf[f].obousmerne.end(); ++i) if (*i == t) break; *i = graf[f].obousmerne.back(); graf[f].obousmerne.pop_back(); } // Prochází obousměrné ulice a orientuje ty, u nichž je orientace vynucená. // Vrátí false, pokud u některé křižovatky nelze naorientovat ulice tak, // aby jich vcházel a vycházel stejný počet. static bool naorientuj_vynucene(int n) { vector kontroluj; for (int i = 1; i <= n; i++) kontroluj.push_back(i); while (!kontroluj.empty()) { int v = kontroluj.back(); kontroluj.pop_back(); int rozdil = graf[v].ven.size() - graf[v].dovnitr.size(); if (rozdil == 0) continue; if ((unsigned) abs(rozdil) > graf[v].obousmerne.size()) return false; bool ven; if (rozdil == (int) graf[v].obousmerne.size()) ven = false; else if (-rozdil == (int) graf[v].obousmerne.size()) ven = true; else continue; vector::iterator a; for (a = graf[v].obousmerne.begin(); a != graf[v].obousmerne.end(); ++a) { smaz_obousmernou_hranu(*a, v); if (ven) pridej_jednosmernou_hranu(v, *a); else pridej_jednosmernou_hranu(*a, v); kontroluj.push_back(*a); } graf[v].obousmerne.clear(); } return true; } // Naorientuje libovolně cyklus z obousměrných ulic obsahující křižovatku V. static void naorientuj_cyklus(int v) { vector cyklus; vector::iterator i, j; cyklus.push_back(v); int a = graf[v].obousmerne[0], p = v; while (a != v) { i = graf[a].obousmerne.begin(); cyklus.push_back(a); if (p == *i) ++i; p = a; a = *i; } cyklus.push_back(v); for (i = cyklus.begin(), j = i + 1; j != cyklus.end(); ++i, ++j) { pridej_jednosmernou_hranu(*i, *j); graf[*i].obousmerne.clear(); } } // Naorientuje libovolně cykly z obousměrných ulic. static void naorientuj_cykly(int n) { for (int v = 1; v <= n; v++) if (!graf[v].obousmerne.empty()) naorientuj_cyklus(v); } // Nalezne a vypíše procházku, která projde každou ulicí právě jednou // a v povoleném směru, za předpokladu, že žádná ulice není obousměrná. static void vypis_eulerovsky_tah() { vector tah; const char *sep = ""; tah.push_back(1); while (!tah.empty()) { int v = tah.back(); if ((unsigned) graf[v].prvni_nepouzita == graf[v].dovnitr.size()) { printf("%s%d", sep, v); sep = " "; tah.pop_back(); } else { hrana *h = graf[v].dovnitr[graf[v].prvni_nepouzita]; tah.push_back(h->z); graf[v].prvni_nepouzita++; } } printf("\n"); } int main() { int m, n; scanf("%d%d", &n, &m); graf = new krizovatka[n + 1]; for (int i = 0; i < m; i++) { int f, t; char sm[2]; scanf("%d%d%s", &f, &t, sm); if (sm[0] == 'J') pridej_jednosmernou_hranu(f, t); else { graf[f].obousmerne.push_back(t); graf[t].obousmerne.push_back(f); } } for (int i = 0; i < n; i++) if ((graf[i].dovnitr.size() + graf[i].ven.size() + graf[i].obousmerne.size()) % 2 == 1) { printf("nelze\n"); return 0; } if (pocet_dostupnych(1) != 2*m || !naorientuj_vynucene(n)) { printf("nelze\n"); return 0; } naorientuj_cykly(n); vypis_eulerovsky_tah(); return 0; }