感觉上判是否能一次完成是困难的。设两次的路径长度分别为 \(a, b\),考虑一些特殊情况。
题目一定有解,考虑取出一棵生成树。可以发现,第二次操作时的边数实际上很多,感觉上对于 \(b\) 不能限制得太小。考虑 \(a\) 较小的情况。
事实上我们想解决的是如下问题:选定一个 \(b\),对于任意的 \((s,t)\),要么 \(\operatorname{dist}(s,t)=1\) 或 \(a\),要么从 \(s\),每次走 \(1\) 或 \(a\) 的距离,能够恰好 \(b\) 步到达 \(t\)。
对于 \(a=3\),可以发现每步一定会改变深度奇偶性,因此步数的奇偶性确定了,不太能做。而如果 \(a\ge 4\),路径形态比较复杂。因此考虑 \(a=2\) 的情形。
首先 \(b\) 有一个下界为 \(\lceil\frac{D+1}{2}\rceil\),其中 \(D\) 为直径长度。事实上我们也能构造出 \(b=D\) 的方案。
考虑一条链 \(s\to t\),其长度为 \(d\)。
如果 \(d\ge D\),那么我们在这条链上不停跳 \(=2\) 的距离,然后一段后缀一步步走即可。
如果 \(d<D\),此时我们找出距离 \(s\) 最远点 \(x\),设 \(x\) 在 \(s\to t\) 的最近点为 \(p\),那么 \(s\to t\) 上的边还是一步步走,然后再在 \(p\to x\) 这条链上通过 \(1\to 3\to\cdots 2k+1\to 2k\to \cdots\to 2\) 状物消耗剩余步数即可。
#include <bits/stdc++.h>
using namespace std;const int kN = 205;
int n, m;
bool vis[kN];
bool e[kN][kN];
vector<int> tr[kN];
vector<int> path[kN][kN];void DFS(int x) {vis[x] = 1;for(int to = 1; to <= n; to++) {if(vis[to] || !e[x][to]) continue;tr[x].push_back(to);tr[to].push_back(x); DFS(to);}
}void DFS2(int x, int fa, vector<int> v, int rt) {v.push_back(x);path[rt][x] = v;for(int to : tr[x]) {if(to != fa) DFS2(to, x, v, rt);}
}void Clear() {memset(vis, 0, sizeof(vis));memset(e, 0, sizeof(e));fill_n(tr, n + 3, vector<int> {});for(int i = 1; i <= n; i++) {fill_n(path[i], n + 3, vector<int> {});}
}void Solve() {cin >> n >> m;Clear();for(int i = 1; i <= m; i++) {int u, v;cin >> u >> v;e[u][v] = e[v][u] = 1;}DFS(1);for(int i = 1; i <= n; i++) {DFS2(i, 0, vector<int> {}, i);}int x = 0, y = 0, dia = -1;for(int i = 1; i <= n; i++) {for(int j = i + 1; j <= n; j++) {int len = path[i][j].size() - 1;if(dia < len) dia = len, x = i, y = j;}}cout << "2\n";{vector<tuple<int, int, int>> edge;for(int i = 1; i <= n; i++) {for(int j = i + 1; j <= n; j++) {if(e[i][j]) continue;for(int k = 1; k <= n; k++) {if(e[k][i] && e[k][j]) {edge.emplace_back(i, k, j);break;}}}}cout << "3\n";cout << edge.size() << "\n";for(auto k : edge) {int x, y, z;tie(x, y, z) = k;cout << x << " " << y << " " << z << "\n";e[x][z] = e[z][x] = 1;}}int len = (dia + 1) / 2;vector<vector<int>> ans;for(int i = 1; i <= n; i++) {for(int j = i + 1; j <= n; j++) {if(e[i][j]) continue;int dis = path[i][j].size() - 1;vector<int> p;if(dis >= len) {for(int k = 0; k <= dis; k += 2) {p.push_back(path[i][j][k]);if(p.size() + (dis - k) == len + 1) {while(k < dis) p.push_back(path[i][j][++k]);break;}}ans.push_back(p);continue;}if(path[i][x].size() < path[i][y].size()) swap(x, y);int nd = len - dis, t = 0;while((t + 1 < path[i][j].size()) && (path[i][j][t + 1] == path[i][x][t + 1])) t++;if(path[i][x][1] != path[i][j][1]) {p.push_back(i);vector<int> v = path[i][x];for(int k = 2; k <= nd; k += 2) {p.push_back(v[k]);}for(int k = nd - !(nd & 1); k >= 1; k -= 2) {p.push_back(v[k]);}for(int k = 1; k < path[i][j].size(); k++) {p.push_back(path[i][j][k]);}}else {for(int k = 0; k < t; k++) {p.push_back(path[i][j][k]);}vector<int> v;for(int k = t; k < path[i][x].size(); k++) {v.push_back(path[i][x][k]);}for(int k = 1; k <= nd; k += 2) {p.push_back(v[k]);}for(int k = nd - (nd & 1); k >= 1; k -= 2) {p.push_back(v[k]);}for(int k = t; k < path[i][j].size(); k++) {p.push_back(path[i][j][k]);}}ans.push_back(p);}}cout << len + 1 << "\n";cout << ans.size() << "\n";for(vector<int> v : ans) {for(int i : v) cout << i << " ";cout << "\n";}
}int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);ios::sync_with_stdio(0), cin.tie(0);int t;cin >> t;while(t--) Solve();return 0;
}