#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include using namespace std; using namespace std::chrono; const int MAX_VERT = 100000; const int MAX_EDGES = 500000; struct edge { int s, e; }; int N, K, M; edge edges[MAX_EDGES]; int vert[MAX_VERT]; long long max_path = 0; typedef vector< vector > edges_map_t; edges_map_t edges_map; time_point end_time(steady_clock::now() + milliseconds(4700)); class my_runtime_error : public runtime_error { const int _i; public: my_runtime_error(const string& msg, int i) : runtime_error(msg) , _i(i) {} int i() const { return _i; } }; struct FILE_closer { FILE* fd; FILE_closer(FILE* fd_) { fd = fd_; } ~FILE_closer() { if (fd) fclose(fd); } operator FILE*() const { return fd; } }; void read(const char* fname) { FILE_closer fin = fopen(fname, "rt"); if (!fin) throw runtime_error("failed to open input stream"); int c = fscanf(fin, "%d", &N); if (c != 1 || N <= 1 || N > MAX_VERT) throw my_runtime_error("invalid N", 1); c = fscanf(fin, "%d", &K); if (c != 1 || K < 1 || K > MAX_EDGES) throw my_runtime_error("invalid K", 2); vector cnt; cnt.resize(N + 1); for (int i = 0; i < K; i++) { int s, e; c = fscanf(fin, "%d", &s); if (c != 1 || s < 1 || s > N) { throw my_runtime_error("invalid edge start", 3); } c = fscanf(fin, "%d", &e); if (c != 1 || e < 1 || e > N) { throw my_runtime_error("invalid edge end", 4); } if (e == s) { throw my_runtime_error("invalid edge pair", 5); } cnt[s]++; cnt[e]++; edges[i].s = s < e ? s : e; edges[i].e = s < e ? e : s; } edges_map.resize(N + 1); for (int i = 1; i <= N; i++) { edges_map[i].reserve(cnt[i]); } sort(edges, edges + K, [](const edge& le, const edge& re) -> bool { return le.s != re.s ? le.s > re.s : le.e > re.e; }); for (int i = 0; i < K; i++) { const edge &ed = edges[i]; edges_map[ed.s].push_back(ed.e); edges_map[ed.e].push_back(ed.s); } for (edges_map_t::iterator it(edges_map.begin()), en(edges_map.end()); it != en; it++) { sort(it->begin(), it->end(), [](int l, int r) -> bool { return l > r; }); } } template long long calc_path(IterT s, IterT e) { long long path = 0, i = 1; for (IterT it = s; it != e; it++, i++) { path += i * *it; } return path; } struct solve { vector vs, vsmax; vector in_use; vector::const_iterator> vslast; long long my_max_path = 0; void search_end(int prev) { while (steady_clock::now() < end_time) { const vector& edges = edges_map[prev]; if (edges.empty()) { break; } vector::const_iterator it(edges.begin()), en(edges.end()); while (steady_clock::now() < end_time && it != en && in_use[*it]) it++; if (steady_clock::now() >= end_time || it == en) { break; } in_use[prev] = true; vs.push_back(prev); vslast.push_back(it); prev = *it; } vs.push_back(prev); long long path = calc_path(vs.rbegin(), vs.rend()); if (my_max_path < path) { vsmax = vs; my_max_path = path; } vs.pop_back(); } solve() { vs.reserve(K); vsmax.reserve(K); vslast.reserve(K); in_use.resize(K + 1); int prev = edges[0].e; search_end(prev); while (!vs.empty() && steady_clock::now() < end_time) { const vector& edges = edges_map[vs.back()]; const vector::const_iterator& next = ++vslast.back(); if (next != edges.end()) { if (!in_use[*next]) { search_end(*next); } } else { in_use[vs.back()] = false; vs.pop_back(); vslast.pop_back(); } } if (max_path < my_max_path) { max_path = my_max_path; M = vsmax.size(); copy(vsmax.rbegin(), vsmax.rend(), vert); } } }; char buff[1000000]; void write(const char* fname) { char *ptr = buff; ptr += sprintf(ptr, "%d\n", M); for (int i = 0; i < M; i++) { ptr += sprintf(ptr, "%d\n", vert[i]); } FILE_closer fout = fopen(fname, "wt"); if (!fout) throw my_runtime_error("failed to open output stream", -1); fwrite(buff, ptr - buff, 1, fout); } #define FNAME "maxpath" int main() { try { time_point start = steady_clock::now(); read(FNAME ".in"); time_point rt = steady_clock::now(); solve s; time_point st = steady_clock::now(); write(FNAME ".out"); time_point wt = steady_clock::now(); milliseconds wd = duration_cast(wt - st); milliseconds sd = duration_cast(st - rt); milliseconds rd = duration_cast(rt - start); //return sd.count() / 10 * 1000000 + wd.count() / 10 * 1000 + rd.count() / 10; } catch (const my_runtime_error& ex) { cerr << ex.what() << endl; return ex.i(); } return 0; }