#include using namespace std; struct Edge { int u, v, w; }; static const int MAXW = 200; int N; vector edges; vector>> g; // to, edge_id(1-based) set sq; bool isSquare(int x) { return sq.count(x); } bool dfs_path(int cur, int target, vector& vis, vector& path, int sum, vector& ans) { if (cur == target) { if (isSquare(sum)) { ans = path; return true; } return false; } vis[cur] = 1; for (auto [to, eid] : g[cur]) { if (vis[to]) continue; path.push_back(eid); if (dfs_path(to, target, vis, path, sum + edges[eid - 1].w, ans)) { return true; } path.pop_back(); } vis[cur] = 0; return false; } bool find_any_square_path(int s, int t, vector& ans) { vector vis(N + 1, 0), path; ans.clear(); return dfs_path(s, t, vis, path, 0, ans); } bool check_all(vector>& allPaths) { allPaths.clear(); for (int i = 1; i <= N; i++) { for (int j = i + 1; j <= N; j++) { vector p; if (!find_any_square_path(i, j, p)) return false; allPaths.push_back(p); } } return true; } void build_graph(const vector>& extraEdges, const vector& weights) { edges.clear(); // path edges for (int i = 1; i < N; i++) { edges.push_back({i, i + 1, weights[i - 1]}); } // extra edges for (int i = 0; i < (int)extraEdges.size(); i++) { edges.push_back({extraEdges[i].first, extraEdges[i].second, weights[N - 1 + i]}); } g.assign(N + 1, {}); for (int i = 0; i < (int)edges.size(); i++) { int id = i + 1; g[edges[i].u].push_back({edges[i].v, id}); g[edges[i].v].push_back({edges[i].u, id}); } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> N; for (int i = 1; i * i <= 10000; i++) sq.insert(i * i); // Chỉ là một số pattern thử nghiệm. // Bạn có thể đổi / thêm pattern khác. vector>> patterns; // Pattern 1: thêm (1,3), (1,4), ..., (1,N) { vector> ex; for (int v = 3; v <= N; v++) ex.push_back({1, v}); patterns.push_back(ex); } // Pattern 2: thêm (i, i+2) { vector> ex; for (int i = 1; i + 2 <= N; i++) ex.push_back({i, i + 2}); patterns.push_back(ex); } // Pattern 3: xen kẽ một ít cạnh về 1 và cạnh chéo { vector> ex; for (int i = 3; i <= N; i++) { if (i & 1) ex.push_back({1, i}); else if (i - 2 >= 1) ex.push_back({i - 2, i}); } patterns.push_back(ex); } mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); for (auto& extraEdges : patterns) { int M = (N - 1) + (int)extraEdges.size(); if (M > 2 * N - 3) continue; vector pool(MAXW); iota(pool.begin(), pool.end(), 1); for (int attempt = 0; attempt < 30000; attempt++) { shuffle(pool.begin(), pool.end(), rng); vector weights(pool.begin(), pool.begin() + M); build_graph(extraEdges, weights); vector> allPaths; if (check_all(allPaths)) { cout << M << '\n'; for (auto &e : edges) { cout << e.u << ' ' << e.v << ' ' << e.w << '\n'; } for (auto &p : allPaths) { cout << p.size(); for (int x : p) cout << ' ' << x; cout << '\n'; } return 0; } } } // Không tìm được bằng brute thử nghiệm cout << -1 << '\n'; return 0; }