原题链接 位于CodeForceshttps://codeforces.com/problemset/problem/28/B
One day n cells of some array decided to play the following game. Initially each cell contains a number which is equal to it's ordinal number (starting from 1). Also each cell determined it's favourite number. On it's move i-th cell can exchange it's value with the value of some other j-th cell, if |i - j| = di, where di is a favourite number of i-th cell. Cells make moves in any order, the number of moves is unlimited.
The favourite number of each cell will be given to you. You will also be given a permutation of numbers from 1 to n. You are to determine whether the game could move to this state.
Input
The first line contains positive integer n (1 ≤ n ≤ 100) — the number of cells in the array. The second line contains n distinct integers from 1 to n — permutation. The last line contains n integers from 1 to n — favourite numbers of the cells.
Output
If the given state is reachable in the described game, output YES, otherwise NO.
Examples
input
5 5 4 3 2 1 1 1 1 1 1output
YES
input
7 4 3 5 1 2 7 6 4 6 6 1 6 6 1output
NO
input
7 4 2 5 1 3 7 6 4 6 6 1 6 6 1output
YES
这道题需要我们用到并查集,即可以 合“并” 和”查“询 的多个集合
依照题意,数组每个位置的“favourite”就是能与其交换的数组位置,只要我们将所有能交换的数组下标放到一个连通块里,最后查询每个数组的下标与数是否都在一个连通块里就可以判断它是否能够进入自己的位置了,如果有数字不在一个连通块则输出NO
#include <stdio.h>
#include <iostream>
using namespace std;
int dsu[110]; // 并查集
int num[110];
int find(int x) // “查”
{
return x == dsu[x] ? x : dsu[x] = find(dsu[x]);
}
void merge(int x, int y) // “并”
{
x = find(x);
y = find(y);
dsu[x] = y;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <=n; i++) dsu[i] = i; // 并查集初始化
for (int i = 1; i <=n; i++) scanf("%d", &num[i]);
int t;
for (int i = 1; i <= n; i++)
{
scanf("%d", &t);
if (i-t >= 1) merge(i, i-t);
if (i+t <= n) merge(i, i+t);
}
for (int i = 1; i <= n; i++)
if (find(i) != find(num[i])) // 查询是否在同一个连通块
{
printf ("NO");
return 0;
}
printf ("YES");
return 0;
}