Loading

CodeForces 691D:Swaps in Permutation(并查集)

http://codeforces.com/contest/691/problem/D

D. Swaps in Permutation

 

You are given a permutation of the numbers 1, 2, ..., n and m pairs of positions (aj, bj).

At each step you can choose a pair from the given positions and swap the numbers in that positions. What is the lexicographically maximal permutation one can get?

Let p and q be two permutations of the numbers 1, 2, ..., n. p is lexicographically smaller than the q if a number 1 ≤ i ≤ n exists, so pk = qkfor 1 ≤ k < i and pi < qi.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 106) — the length of the permutation p and the number of pairs of positions.

The second line contains n distinct integers pi (1 ≤ pi ≤ n) — the elements of the permutation p.

Each of the last m lines contains two integers (aj, bj) (1 ≤ aj, bj ≤ n) — the pairs of positions to swap. Note that you are given apositions, not the values to swap.

Output

Print the only line with n distinct integers p'i (1 ≤ p'i ≤ n) — the lexicographically maximal permutation one can get.

Example
input
9 6 
1 2 3 4 5 6 7 8 9
1 4
4 7
2 5
5 8
3 6
6 9
output
7 8 9 4 5 6 1 2 3

题意:给出一个含n个元素的序列,再给出m个可以无限次互相交换位置的下标,求出交换以后让整个序列的字典序最大。
思路:用并查集分出可以交换位置的下标集合,然后用vector装每个集合的下标和元素,然后每次查找集合的根节点的时候对每个集合的元素排序一下就好了。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 using namespace std;
 7 #define N 1000005
 8 vector <int> num[N];
 9 vector <int> pos[N];
10 int p[N],a[N],ans[N];
11 int fa[N];
12 
13 int Find(int x)
14 {
15     if(x==fa[x]) return x;
16     return fa[x]=Find(fa[x]);
17 }
18 
19 void Merge(int x,int y)
20 {
21     x=Find(x),y=Find(y);
22     if(x==y) return ;
23     fa[x]=y;
24 }
25 
26 int main()
27 {
28     int n,m;
29     cin>>n>>m;
30     for(int i=1;i<=n;i++){
31         fa[i]=i;
32         scanf("%d",&a[i]);
33         p[i]=i;
34     }
35     for(int i=1;i<=m;i++){
36         int a,b;
37         scanf("%d%d",&a,&b);
38         Merge(a,b);
39     }
40     for(int i=1;i<=n;i++){
41         int x=Find(i);
42         pos[x].push_back(i);
43         num[x].push_back(-a[i]);
44 //因为要从大到小排序,而默认的排序是从小到大,所以先取负后面再取正
45     }
46     for(int i=1;i<=n;i++){
47         sort(num[i].begin(),num[i].end());
48         for(int j=0;j<pos[i].size();j++){
49             ans[pos[i][j]]=-num[i][j];
50         }
51     }
52     for(int i=1;i<=n;i++){
53         printf("%d ",ans[i]);
54     }
55     return 0;
56 }

 

posted @ 2016-07-14 09:56  Shadowdsp  阅读(481)  评论(0编辑  收藏  举报