zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    高并发系统中的常见问题
    区块链需要解决诸多问题
    什么是“区块链”技术
    github源码开源区块链浏览器
    JavaScript 内存
    行为驱动开发(BDD)
    Vue.js
    Net程序员学习Linux
    Mybatis数据操作
    Metatable和Metamethod(转)
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5669332.html
Copyright © 2011-2022 走看看