#include #include #include #define MAXN 1000000 using namespace std; // Struktura popisující hranu (výchozí vrchol dle umístění v poli) struct hrana { int kam; int rozdil; }; int oznaceni_vrcholu[MAXN]; // Pole s napěťovou hladinou vrcholů vector hrany_vrcholu[MAXN]; // pole se seznamy hran u vrcholů /*** * DFS na procházení dvojkových komponent, dostává dva argumenty: * kde -- jaký vrchol označit * oznaceni -- jakou haldinou chceme označit vrchol (-1 pokud je to jedno) */ int dfs_02(int kde, int oznaceni) { if (oznaceni_vrcholu[kde] != -1) { // Už máme označený zkoumaný vrchol if (oznaceni == -1 || oznaceni_vrcholu[kde] == oznaceni) // Shoduje-li se označení nebo je jedno čím označíme tak úspěch return 1; // Jinak dostáváme spor return 0; } if (oznaceni == -1) // Už víme, že vrchol musíme označit, pokud je nám jedno jak, tak hladinou 0 oznaceni = 0; oznaceni_vrcholu[kde] = oznaceni; // Přiřadíme vrcholu příslušnou hladinu int ok = 1; int kam; for (int i = 0; i < hrany_vrcholu[kde].size(); ++i) { if (hrany_vrcholu[kde][i].rozdil != 1) { // Zavoláme toto dfs na všechny hrany s rozdílem dva nebo nula a vyhodnotíme jestli tu došlo ke sporu // Chtěné označení tohoto vrcholu můžeme získat jako XOR výchozího vrcholu a rozdílu na hraně ok &= dfs_02(hrany_vrcholu[kde][i].kam, oznaceni ^ hrany_vrcholu[kde][i].rozdil); } else { // Zpracováváme hranu s rozdílem jedna, tak se jí pokusíme rovnou označit; případně zjistíme jestil nedošlo ke sporu další DFS ale nevoláme kam = hrany_vrcholu[kde][i].kam; // Pouze pomocná proměnná pro větší srozumitelnost kódu if (oznaceni_vrcholu[kam] != -1) { // Vrchol už je označený -- musí mít jedničku ok &= (oznaceni_vrcholu[kam] == 1); } else { // Vrchol ještě není označený, tak mu nastavíme hladninu jedna oznaceni_vrcholu[kam] = 1; } } } return ok; } /*** * DFS na procházení zbylých hran, dostává dva argumenry: * kde -- jaký vrchol chceme označit * oznaceni -- jakou hladinou jej chceme označit */ int dfs_01(int kde, int oznaceni) { if (oznaceni_vrcholu[kde] != -1) { // Už máme označený zkoumaný vrchol return oznaceni_vrcholu[kde] == oznaceni; // Vrátíme jeslti se označení shodují } oznaceni_vrcholu[kde] = oznaceni; // Označíme vrchol příslušnou hladinou int ok = 1; for (int i = 0; i < hrany_vrcholu[kde].size(); ++i) { // Zavoláme dfs na všechny inclidentní hrany a budeme se je snažit obarvit barvou "moje barva XOR ohodnocení hrany" ok &= dfs_01(hrany_vrcholu[kde][i].kam, oznaceni ^ hrany_vrcholu[kde][i].rozdil); // Hlídáme si, že ani jedno dfs nenarazilo na spor } return ok; } /*** * Formát vstupu: * int n, m -- počet uzlů a počet vodičů * m řádků formátu "a b h", kde "a" a "b" jsou indexy vrcholů, který * daná hrana spojuje a h je 0, 1 nebo 2 podle rozdílu na vodiči */ int main() { int i, j, a, b, h; int n, m; scanf("%d%d", &n, &m); queue dvojkove_vrcholy; // Budeme si udržovat frontu vrcholů inidentní s nějakou dvojkovou hranou, // pak pustíme dfs na tyto vrcholy a projdeme tak všechny komponenty s dvojkovými hranami // Inicializace označení vrcholů for (i = 0; i < n; ++i) oznaceni_vrcholu[i] = -1; // Načítání vstupu for (i = 0; i < m; ++i) { scanf("%d%d%d", &a, &b, &h); hrany_vrcholu[a].push_back( (struct hrana) {b, h} ); hrany_vrcholu[b].push_back( (struct hrana) {a, h} ); if (h == 2) { // Pokud máme dvojkovou hranu, tak zařadíme vrcholy do fronty (zařadíme vrcholy i vícekrát, ale maximálně jich tam bude 2m) dvojkove_vrcholy.push(a); dvojkove_vrcholy.push(b); } } while (!dvojkove_vrcholy.empty()) { // Označíme vrcholy ve dvojkových komponentách if (!dfs_02(dvojkove_vrcholy.front(), -1)) { // Ověříme, že všechna označení proběhla vpořádku // Pokud jsme dostali spor vypíšeme -1 a končíme printf("-1\n"); return 0; } dvojkove_vrcholy.pop(); } for (i = 0; i < n; ++i) { // Projdeme všechny vrcholy abychom spustili dfs ze sousedů vrcholů již označených jedničkou if (oznaceni_vrcholu[i] == 1) { // Našli jsme jedničkový vrchol, projdeme všechny jeho sousedy for (j = 0; j < hrany_vrcholu[i].size(); ++j) { if (!dfs_01(hrany_vrcholu[i][j].kam, 0)) { // Chceme je označovat nulovou hladinou // Dostali jsme spor -- vypíšeme -1 a ukončíme printf("-1\n"); return 0; } } } } // Vypíšeme řešení for (i = 0; i < n; ++i) { printf("%d\n", oznaceni_vrcholu[i]); } return 0; }