0%

765. 情侣牵手

765.情侣牵手

题目描述:

$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;
}
};