#include #include using namespace std; // Nodo struct nodo { vector adj; int parent; bool marked; nodo() { parent = -1; marked = false; } }; // Convoglio (DAG) vector conv; // Eventuale ciclo trovato vector cpath; // Eventuale perfect matching (messaggio - nave - messggio - nave - messaggio - nave ...) vector perfmatch; // Visita che trova un ciclo (la classica dfs che segna il padre di ogni nodo saltando sempre messaggio - nave o nave - messaggio) bool visit(int n, int p) { unsigned int i; nodo* nod = &conv[n]; // Segno il padre nod->parent = p; // Inizio a lavorare sul nodo nod->marked = true; // Visita nodi adiacenti for (i = 0; i < nod->adj.size(); i++) { // Se il nodo adiacente è marcato significa che ho trovato un ciclo!!! if (conv[nod->adj[i]].marked) { // Il ciclo parte dal nodo adiacente cpath.push_back(nod->adj[i]); // Devo aggiungere anche il nodo corrente nella visita, poiché anche lui fa parte del ciclo cpath.push_back(n); // Riempio il resto del ciclo risalendo i padri ed arrivando al nodo adiacente while (n != nod->adj[i]) { n = conv[n].parent; cpath.push_back(n); } // Ciclo trovato, fine return true; } // Se arrivo qui, il nodo adiacente non è marcato, quindi lancia la visita su di lui // Se è già stato visitato in precedenza però salto // Occhio che se il nodo adiacente mi genera un ciclo, essendo in ricorsione lo devo sparare in alto per femare tutto if (conv[nod->adj[i]].parent == -1 && visit(nod->adj[i], n)) return true; } // Fine visita nodo corrente nod->marked = false; // Se arrivo qui non ho trovato alcun ciclo return false; } int main() { // Input ifstream input("input.txt"); int mess, edg, i, n1, n2; unsigned int j; input >> mess >> edg; // Allocazione conv.assign(mess * 2, nodo()); perfmatch.assign(mess * 2, -1); // Riempio il DAG // Leggo prima la corrispondenza univoca di Turing (i primi mess nodi sono i messaggi) for (i = 0; i < mess; i++) { input >> n1 >> n2; // Aggiungo il collegamento messaggio - nave conv[n1].adj.push_back(n2 + mess); } // Leggo i possibili collegamenti messaggio - nave (i prossimi edg - mess nodi sono le navi) for (; i < edg; i++) { input >> n1 >> n2; // Aggiungo il collegamento nave - messaggio conv[n2 + mess].adj.push_back(n1); } // Output ofstream output("output.txt"); // Lancio la visita per ogni nodo cercando un ciclo for (i = 0; i < mess; i++) { // Scarto quei nodi già esaminati da visite precedenti while (i < mess && conv[i].parent != -1) i++; // Se ho finito i nodi esco, poiché se avessi trovato un ciclo lo avrei già stampato e sarei già uscito if (i == mess) break; // Visito a partire dal nodo corrente if (visit(i, i) == true) { // Se sono qui ho trovato un ciclo e l'ho memorizzato in cpath // Devo andare a pescare la coppia messaggio - nave // Sapendo che i nodi messaggio si alternano a quelli delle navi (per come è costruito il DAG) for (j = 0; j < cpath.size() - 1; j += 2) perfmatch[cpath[j]] = cpath[j + 1]; // Stampo (se un collegamento del matching è mancante, devo prendere il primo dei nodi adiacenti) // Sottraggo mess al nodo nave perché li uso tutti assieme nel DAG, ma il contatore dovrebbe partire da 0 anche per le navi for (i = 0; i < mess; i++) { if (perfmatch[i] == -1) output << i << " " << conv[i].adj[0] - mess << endl; else output << i << " " << perfmatch[i] - mess << endl; } // Esco dopo aver stampato return 0; } } // Se sono arrivato qui non ho trovato alcun ciclo output << -1 << endl; return 0; }