题目描述
有一个由 n n n 个元素组成的序列 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an;最初,序列中的每个元素满足 a i = i a_i=i ai=i。
对于每次操作,你可以交换序列中第 i i i 个元素和第 j j j 个元素当且仅当满足 ∣ i − j ∣ = d i |i−j|=d_i ∣i−j∣=di。
题目给出序列 b 1 , b 2 , … , b n b_1,b_2,…,b_n b1,b2,…,bn 和 d 1 , d 2 , … , d n d_1,d_2,…,d_n d1,d2,…,dn,询问是否可以通过若干次交换,使得序列 a a a 和序列 b b b 完全相同。
输入格式
第 1 1 1 行一个正整数 n n n,含义如上。
第 2 2 2 行 n n n 个正整数表示 b 1 , b 2 , … , b n b_1,b_2,…,b_n b1,b2,…,bn。
第 3 3 3 行 n n n 个正整数表示 d 1 , d 2 , … , d n d_1,d_2,…,d_n d1,d2,…,dn。
输出格式
若能,输出 YES
;否则输出 NO
。
输入 #1
7
4 2 5 1 3 7 6
4 6 6 1 6 6 1
输出 #1
YES
输入 #2
7
4 3 5 1 2 7 6
4 6 6 1 6 6 1
输出 #2
NO
数据范围
1 ≤ n , d i ≤ 100 1≤n,d_i≤100 1≤n,di≤100。保证序列 b b b 中元素不重复。
补充说明
原题:CF28B pSort | 洛谷
解题思路
对于题意的理解如下:
if (abs(i - j) == d[i] || abs(i - j) == d[j]) {
/* i,j是可交换的 */
}
那么我们可以把 a a a序列抽象为一张无向图,可交换关系为无向边。
则强连通分量之内的节点可以随意交换。
也就是说,如果需要交换所有节点都在同一个强连通分量之中,就输出YES
;
反之,如果需要交换的任意一对节点不在一个强连通分量中,就输出NO
。
接下来实现代码:
我们采用染色法标记不同的强连通分量,用广度优先搜索对整张图进行染色,时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
void bfs(int bg) {
color++;
q.push(bg);
int head, next, i;
while (!q.empty()) {
head = q.front();
q.pop();
if (book[head]) continue;
book[head] = true;
colors[head] = color;
for (i = 1; i <= n; i++) {
if (i == head) continue;
next = abs(head - i);
if (next == ds[head] || next == ds[i]) q.push(i);
}
}
}
我们需要遍历每一个节点进行尝试,所以算法总时间复杂度为 O ( n 3 ) O(n^3) O(n3),可以接受。
for (i = 1; i <= n; i++) {
if (!colors[i]) bfs(i);
}
最后,AC代码如下:
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
const int max_n = 100;
int bs[max_n], ds[max_n];
int colors[max_n], color = 0;
queue<int>q;
int book[max_n];
int n;
void bfs(int bg) {
color++;
q.push(bg);
int head, next, i;
while (!q.empty()) {
head = q.front();
q.pop();
if (book[head]) continue;
book[head] = true;
colors[head] = color;
for (i = 1; i <= n; i++) {
if (i == head) continue;
next = abs(head - i);
if (next == ds[head] || next == ds[i]) q.push(i);
}
}
}
int main() {
cin >> n;
int i;
for (i = 1; i <= n; i++) cin >> bs[i];
for (i = 1; i <= n; i++) cin >> ds[i];
for (i = 1; i <= n; i++) {
if (!colors[i]) bfs(i);
}
for (i = 1; i <= n; i++) {
if (colors[bs[i]] != colors[i]) {
cout << "NO" << endl;
return 0;
}
}
cout << "YES" << endl;
return 0;
}