题目描述:
$n$ 对情侣坐在连续的 $2n$ 个座位上,人和座位由一个整数数组 $row$ 表示,其中 $row[i]$ 是坐在第 $i$ 个座位上的人的 $ID$ 。情侣们按顺序编号,第一对是 $(0, 1)$ ,第二对是 $ (2, 3)$ ,以此类推,最后一对是 $(2n-2, 2n-1)$ 。
返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起。每次交换可选择任意两人,让他们站起来交换座位。
数据范围:
$2\le n \le 30$
题解:
循环置换关系,假设有 $n$ 对坐错位置,那么每次交换可以解决一个冲突,最后一次交换时可以消除两个冲突。因此可以求出连通块的大小,每个连通块需要的交换次数是连通块的大小减一。使用并查集,每次将错误座位的情侣编号连接,可以使用 $size$ 数组维护连通块大小,也可以直接返回 $n - count$ , $count$ 为连通块个数。
也可以直接 $dfs$ ,不用回溯,直接求解即可。
也可以直接贪心求解。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| auto optimize_cpp_stdio = []() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); return 0; }(); class Solution { public: const static int maxn = 1e5 + 10; const static int maxm = 1e5 + 10; const static int INF = 0x3f3f3f3f; struct UF { vector<int> fa; vector<int> size; int count; UF(int n) : fa(n), count(n), size(n) { for (int i = 0; i < n; ++i) { fa[i] = i; size[i] = 1; } } int find(int u) { return u == fa[u] ? u : fa[u] = find(fa[u]); } void unite(int u, int v) { int up = find(u), vp = find(v); if (up != vp) { fa[up] = vp; count--; size[vp] += size[up]; } } bool connect(int u, int v) { return find(u) == find(v); } int getCount() { return count; } }; int minSwapsCouples(vector<int> &row) { int n = row.size() / 2; UF uf(n); for (int i = 0, j; i < n * 2; i = i + 2) { j = i + 1; row[i] /= 2; row[j] /= 2; if (row[i] != row[j]) { uf.unite(row[i], row[j]); } } int ans = 0; for (int i = 0; i < n; ++i) { if (uf.find(i) == i) { ans += uf.size[i] - 1; } } return ans; } };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| auto optimize_cpp_stdio = []() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); return 0; }(); class Solution { public: const static int maxn = 1e5 + 10; const static int maxm = 1e5 + 10; const static int INF = 0x3f3f3f3f; int ans = 0; void dfs(int step, int n, vector<bool> &flag, vector<int> &row) { if (step >= n) return; int nex = step + 1; if (flag[nex] == true) { dfs(step + 2, n, flag, row); } else { for (int i = nex + 1; i < n; ++i) { if ((row[step] ^ row[i]) == 1) { swap(row[nex], row[i]); ans++; flag[nex] = true; if ((row[i] ^ row[i ^ 1]) == 1) { flag[i] = flag[i ^ 1] = true; } dfs(step + 2, n, flag, row); } } } } int minSwapsCouples(vector<int> &row) { int n = row.size(); vector<bool> flag(n); for (int i = 0; i < n; i = i + 2) { flag[i] = true; flag[i + 1] = ((row[i] ^ row[i + 1]) == 1); } dfs(0, n, flag, row); return ans; } };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| auto optimize_cpp_stdio = []() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr); return 0; }(); class Solution { public: const static int maxn = 1e5 + 10; const static int maxm = 1e5 + 10; const int INF = 0x3f3f3f3f; int minSwapsCouples(vector<int> &row) { int n = row.size(); vector<int> pos(n); for (int i = 0; i < n; ++i) { pos[row[i]] = i; } int cnt = 0; for (int i = 0; i < n; i += 2) { if ((row[i] ^ row[i + 1]) != 1) { int oldi = row[i + 1]; int newi = row[i] ^ 1; swap(row[pos[row[i + 1]]], row[pos[row[i] ^ 1]]); pos[oldi] = pos[newi]; cnt++; } } return cnt; } };
|