旋转跳跃
思路
当我们可以将 对 看作 条双向边之后,能交换位置的点可以看作是联通的,因此我们会得到若干个连通块,由于 对 的使用次数与顺序不受限制,因此在每一个连通块中可以通过若干次交换不同位置上的值,使得该连通块中的数值从小到大排序,即为该连通块所能得到的最小字典序,将每一个连通块都在块内排序之后,即为最终答案。
时间复杂度:
题解
/** * struct Point { * int x; * int y; * }; */ class Solution { #define maxn 100010 private: vector<int> g[maxn]; vector<int> val, pos; bool vis[maxn]; int p[maxn]; public: /** * 返回牛牛所能得到的字典序最小的排列 * @param n int整型 * @param m int整型 * @param perm int整型vector * @param Pair Point类vector * @return int整型vector */ void dfs(int x, int fa = 0) { if (vis[x]) return; vis[x] = 1; pos.push_back(x); for (auto v: g[x]) { if (v == fa) continue; dfs(v, x); } } vector<int> solve(int n, int m, vector<int>& perm, vector<Point>& Pair) { // write code here for (int i = 1; i <= n; ++i) { g[i].clear(); vis[i] = false; p[i] = perm[i-1]; } for (int i = 0; i < m; ++i) { g[Pair[i].x].push_back(Pair[i].y); g[Pair[i].y].push_back(Pair[i].x); } for (int i = 1; i <= n; ++i) { if (vis[i]) continue; pos.clear(); val.clear(); dfs(i); for (auto j: pos) val.push_back(p[j]); sort(val.begin(), val.end()); sort(pos.begin(), pos.end()); int sz = pos.size(); for (int j = 0; j < sz; ++j) p[pos[j]] = val[j]; } vector<int> ans; for (int i = 1; i <= n; ++i) ans.push_back(p[i]); return ans; } };