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

你可能感兴趣的:(并查集)