0%

Codeforces Round 1081 (Div. 2)-CF-1081-E. Swap to Rearrange(按值进行图论建模)(欧拉回路)

题目大意

题目名称:E. Swap to Rearrange

题目大意

给定两个长度为 nn 的数组 aabb。你可以对任意下标 ii (1in1 \le i \le n) 执行至多一次操作:交换 aia_ibib_i

你的目标是通过选择若干个下标进行交换,使得操作结束后,数组 aa 变成数组 bb 的一个重排(即最终数组 aa 和最终数组 bb 包含完全相同的元素集合,只是顺序可能不同)。

如果可以达成目标,请输出操作次数以及被选择进行交换的下标;如果无法达成,请输出 -1。如果存在多种方案,输出任意一种即可。

输入格式

每个测试点包含多组数据。
第一行包含一个整数 tt (1t1041 \le t \le 10^4),表示测试用例的数量。
对于每个测试用例:

  • 第一行包含一个整数 nn (1n1061 \le n \le 10^6)。

  • 第二行包含 nn 个整数 a1,a2,,ana_1, a_2, \dots, a_n (1ain1 \le a_i \le n)。

  • 第三行包含 nn 个整数 b1,b2,,bnb_1, b_2, \dots, b_n (1bin1 \le b_i \le n)。
    保证所有测试用例中 nn 的总和不超过 10610^6

输出格式

对于每个测试用例:

  • 如果无解,输出 -1。

  • 否则,第一行输出操作次数 ss (0sn0 \le s \le n)。

  • 第二行输出 ss 个整数,表示被交换的下标(下标从 1 开始)。

样例输入

1
2
3
4
5
6
7
8
9
10
11
12
13
4
4
1 1 3 3
2 2 4 4
3
1 2 1
3 3 1
3
1 2 3
2 3 1
4
1 2 2 4
3 1 4 3

样例输出

1
2
3
4
5
6
7
2
2 4
-1
0

2
3 4

样例解释

  • 第一个测试用例
    初始时 a=[1,1,3,3]a=[1, 1, 3, 3]b=[2,2,4,4]b=[2, 2, 4, 4]
    选择下标 2 和 4 进行交换:
    • 交换 a2a_2b2b_2aa 变为 [1,2,3,3][1, \mathbf{2}, 3, 3]bb 变为 [2,1,4,4][2, \mathbf{1}, 4, 4]
    • 交换 a4a_4b4b_4aa 变为 [1,2,3,4][1, 2, 3, \mathbf{4}]bb 变为 [2,1,4,3][2, 1, 4, \mathbf{3}]
      最终 a=[1,2,3,4]a=[1, 2, 3, 4]b=[2,1,4,3]b=[2, 1, 4, 3]。此时 aabb 都包含元素 {1,2,3,4}\{1, 2, 3, 4\},满足条件。

image

  • 第二个测试用例
    无论如何操作,都无法使 aa 成为 bb 的重排,故输出 -1。

  • 第三个测试用例
    不需要任何操作,a=[1,2,3]a=[1, 2, 3]b=[2,3,1]b=[2, 3, 1]。两者包含的元素集合均为 {1,2,3}\{1, 2, 3\},已经是重排关系。输出 0。

思路讲解

我感觉AI唬我呢,左看右看,东看西看,完全没看出这道题目为什么需要用图论。因为说白了,这根本不是一个一一对应的问题,对吧?这和图论有什么关系?无非其实就是要让数量相等呀,这个图论实在难以说有什么联系。所以说,我感觉这个AI其实有点乱写,opus4.6,其实也不过如此吧。

仔细的看了一下,应该这道题就是用图论建模做。我们下面用一张图来说明一下图论建模,它这个图是怎么建的。那为什么这道题目用图文建模呢?我认为这道题目首先不适合使用DP解决,因为你不知道以什么为状态。所以说,用DP解决是不可以,因为状态所需空间太大了,然后,其实我们也没什么工具的,要么就贪心啊,你也很难贪,是吧?所以其实也就图论建模了。

首先呢,我们只关注值,所以说我们所见的图呢,是按值连接的。

image

Codeforces Round 1026 (Div. 2)-CF-1026-E. Melody

就是看了洛谷的题解,体检上的这个人来说,这道题目和CF 1026的E比较相似。我稍微看了一下CF 1026的题面,应该是解法比较相似,都是建图,按值进行图论建模。

剩下的就是找欧拉回路了,哎,怎么就突然扯到欧拉回路了呢?首先我们肯定要找一个回路嘛,如果一个连通分量中每个点的入度和出度一致,那么就说明该连通分量可以变成,或者说,该连通分量就是由一系列环构成的。当然了,由一系列环构成可能不能辅助我们实现,实际上它就是一个回路。我们可以使用欧拉回路的方法,把图中的每条边都消耗掉,欧拉回路是每条边恰好被遍历过一次,就是每条边都被恰好遍历一次组成的闭合路径,就是欧拉回路。这个和我们所说的由一系列环构成是一样的,其实是一个意思。存在欧拉回路的这个条件也很简单,就是每个顶点的度数都是偶数,那么一定存在一条欧拉回路(在联通无向图中)。

不过,由于这里我们不需要求欧拉回路,我们只是想要把这个图给建成一个环形的这个嵌套组合,那么实际上是非常简单的。

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
// 开始图论建模
vector<vector<To_id>> g(N+2);
vector<char> vis_edge(N+2);
for (int i=1;i<=N;++i) {
g[A[i]].push_back({B[i],i,0});
g[B[i]].push_back({A[i],i,1});
}
for (int i=1;i<=N;++i) {
if (SZ(g[i])%2!=0) {
cout<<-1<<"\n";
return;
}
}
vector<ll> ans_ls;
// 我们这里不需要求欧拉回路,我们只是想要把这个图给建成一个环形的这个嵌套组合,那么实际上是非常简单的
for (int st_node=1;st_node<=N;++st_node) {
if (g[st_node].empty()) continue;
ll u=st_node;
while (!g[u].empty()) {
auto [to,id,inv]=g[u].back();
g[u].pop_back();
if (vis_edge[id]) {
continue;
}
vis_edge[id]=true;
if (inv) {
ans_ls.push_back(id);
}
u=to;
}
}
sort(all(ans_ls));
cout<<SZ(ans_ls)<<"\n";
for (auto u:ans_ls) {
cout<<u<<" ";
}
cout<<"\n";

AC代码

AC
https://codeforces.com/contest/2192/submission/363992212