Hlg 1748 【并查集】.cpp

题意:

  n个数编号从1~n..但是并不按顺序排列..

  现在想把他们互换位置最后得到1~n的序列..

  两个数可以交换位置的条件是 |i-j| == bi

  

  输入:n 表示n个数

    a[1], a[2], a[3]..a[i]..a[n]

    b[1], b[2], b[3]..b[i]..b[n]

思路:

  并查集..

  可以这么看..如果两个数在一个集合里,那么这两个数就可以互相交换位置了..

  所以就按照i+-b[i]把可以交换的位置的数和该数的归在一个集合里..

  最后查看是否所有要改的数都在一个集合里..

Tips:

  加的时候加的应该是a[i], 表示把这些数放在一个集合里..

  最后看是不是要改位置的数正好都在一个集合里..

  如果把下标放在一个集合里就没有意义了..

Code:

  

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 
 4 int f[110];
 5 int find(int x)
 6 {
 7     return f[x] == x?x:f[x] = find(f[x]);
 8 }
 9 
10 int n;
11 int a[110], b[110];
12 
13 int main()
14 {
15     freopen("in.txt", "r", stdin);
16     bool flag;
17     while (~scanf("%d", &n)) {
18         flag = true;
19         for (int i = 1; i <= n; ++i)
20             f[i] = i;
21         for (int i = 1; i <= n; ++i)
22             scanf("%d", &a[i]);
23         for (int i = 1; i <= n; ++i)
24             scanf("%d", &b[i]);
25         for (int i = 1; i <= n; ++i) {
26             int ff = find(a[i]), fa, fb;
27             if (i+b[i] < n) fa = find(a[i+b[i]]);
28             if(i-b[i] > 0) fb = find(a[i-b[i]]);
29             if (i+b[i] < n && fa != ff) {
30                 f[fa] = ff;
31             }
32             if (i-b[i] > 0 && fb != ff) {
33                 f[fb] = ff;
34             }
35         }
36         for (int i = 1; i <= n; ++i) {
37             if (find(i) != find(a[i])) {
38                flag = false;
39                break;
40             }
41         }
42         if (flag) puts("YES");
43         else puts("NO");
44 
45     }
46     return 0;
47 }

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1748

原文地址:https://www.cnblogs.com/Griselda/p/3046358.html