#include using namespace std; typedef pair ii; typedef pair, vector> vivi; #define F first #define S second int N; vector> G; vector path_H, path_S; vector lp, pred; vector path_count; vector> preds; int start, fin; void load_input(){ // Nejprve načteme vstup, přičemž zahodíme vrcholy, // které leží před startem a za cílem. cin >> N >> start >> fin; start--; fin--; G.assign(fin-start+1, vector()); uint32_t m =0; for(int i = 0; i < N; i++){ int s; cin >> s; for(int j = 0; j < s; j++){ int x; cin >> x; x--; if(i >= start && i <= fin && x >= start && x <= fin){ G[i-start].push_back(x-start); m++; } } } fin -= start; } vector extra_edges(int src){ // Pro každý vrchol src zjistíme, do kterých vrcholů z něj vedou // aspoň dvě cesty. Tím přidáme virtuální hrany délky 1, které využijeme // v hledání nejdelší cesty (co do počtu setkání) vector res = {}; path_count[src] = {1,src}; for(int u = src; u <= fin; u++){ if(path_count[u].S < src){ continue; } if(path_count[u].F >= 2){ res.push_back(u); } for(const int& v : G[u]){ if(path_count[v].S < src){ path_count[v] = {0, src}; } path_count[v].F += path_count[u].F; if(path_count[v].F >= 2){ path_count[v].F = 2; } } } return res; } bool addValue(ii& p, int val){ if(p.F != -1){ if(p.S != -1){ return false; } p.S = val; return true; } p.F = val; return true; } vivi find_two_paths(int src, int dst){ // Předpokládáme, že mezi vrcholy src a dst existují aspoň dvě cesty. // Najdeme a vrátíme proto libovolné různé dvě. vivi res = {}; preds[src] = {{-1,-1}, src}; for(int u = src; u < dst; u++){ if(preds[u].S != src) continue; for(const int& v : G[u]){ if(v > dst) break; if(preds[v].S != src){ preds[v] = preds[src]; } addValue(preds[v].F, u); if(preds[u].F.S > 0) addValue(preds[v].F, u); } } ii curr = preds[dst].F; if(curr.S == -1){ curr.S = curr.F; } while(curr.F == curr.S && curr.F != -1){ res.F.push_back(curr.F); res.S.push_back(curr.S); curr.F = preds[curr.F].S == src ? preds[curr.F].F.F : -1; curr.S = preds[curr.S].S == src ? preds[curr.S].F.S : -1; } while(curr != preds[src].F){ if(curr.F != -1){ res.F.push_back(curr.F); curr.F = preds[curr.F].S == src ? preds[curr.F].F.F : -1; } if(curr.S != -1){ res.S.push_back(curr.S); curr.S = preds[curr.S].S == src ? preds[curr.S].F.F : -1; } } return res; } void find_longest_path(){ lp.assign(fin+1, -1); pred.assign(fin+1, -1); path_count.assign(fin+1, {-1,-1}); lp[0] = 0; for(int u = 0; u < fin; u++){ if(lp[u] < 0) continue; for(const int& v : G[u]){ if(lp[u] > lp[v]){ lp[v] = lp[u]; pred[v] = u; } } for(const int& v : extra_edges(u)){ if(lp[u] + 1 > lp[v]){ lp[v] = lp[u] + 1; pred[v] = u; } } } } void reconstruct_paths(){ preds.assign(fin+1, {{-1,-1}, -1}); int prev = fin; int p = pred[prev]; path_H.push_back(fin); path_S.push_back(fin); while(p != -1){ vivi path = find_two_paths(p, prev); path_H.insert(path_H.end(), path.F.begin(), path.F.end()); path_S.insert(path_S.end(), path.S.begin(), path.S.end()); prev = p; p = pred[p]; } reverse(path_H.begin(), path_H.end()); reverse(path_S.begin(), path_S.end()); } signed main(){ load_input(); find_longest_path(); reconstruct_paths(); for(const int& i : path_H){ cout << i+start+1 << " "; } cout << "\n"; for(const int& i : path_S){ cout << i+start+1 << " "; } cout << "\n"; }