Codeforces 28B. pSort (並查集)
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
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.
Example
Input5Output
5 4 3 2 1
1 1 1 1 1
YESInput
7Output
4 3 5 1 2 7 6
4 6 6 1 6 6 1
NOInput
7Output
4 2 5 1 3 7 6
4 6 6 1 6 6 1
YES
分析:
需要判斷每個數是否能移動到它所指定的位置上,
這裏兩個數經過一些中間量進行位置交換的時候,不影響中間量的位置。
所以可以獨立的判斷每次交換。
這裏我們把能夠互相交換的序號放在同一個集合裏,運用並查集來判斷每個數能否移動到指定位置
代碼如下:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int pre[110]; int n; int id[110]; int val[110]; int Find(int x) { int h=x,tmp; while(pre[x]!=x) x=pre[x]; while(h!=x) { tmp=pre[h]; pre[h]=x; h=tmp; } return x; } void init() { for(int i=1;i<=n;i++) pre[i]=i; } void join(int x,int y) { int p=Find(x); int q=Find(y); if(p!=q) pre[p]=q; } int main() { ios::sync_with_stdio(false); cin>>n; init(); int x,flag; flag=1; for(int i=1;i<=n;i++) { cin>>x; id[x]=i; } for(int i=1;i<=n;i++) cin>>val[i]; for(int i=1;i<=n;i++) { if(i-val[i]>=1) join(i,i-val[i]); if(i+val[i]<=n) join(i,i+val[i]); } for(int i=1;i<=n;i++) { if(Find(id[i])!=Find(i)) { flag=0; break; } } if(flag==1)puts("YES"); else puts("NO"); return 0; }
Codeforces 28B. pSort (並查集)