题意:给出一个含n个元素的序列,再给出m个可以无限次互相交换位置的下标,求出交换以后让整个序列的字典序最大
用并查集分出可以交换位置的下标集合,也就是将可以交换的下标集合分类,然后同一类就倒序输出,这样可以得到字典序最大的解
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define maxn 1000009
using namespace std;
int n, m, a[maxn], b[maxn], c[maxn], father[maxn], ans[maxn];
vector <int> num[maxn], pos[maxn];
int get_father (int x)
{
if (father[x] == x)
return x;
return get_father (father[x]);
}
bool cmp (int x, int y)
{
return x > y;
}
int main ()
{
cin >> n >> m;
rep (i, 1, n)
scanf ("%d", &a[i]);
rep (i, 1, m)
scanf ("%d%d", &b[i], &c[i]);
rep (i, 1, n)
father[i] = i;
rep (i, 1, m)
{
int ta = get_father (b[i]), tb = get_father (c[i]);
if (ta != tb)
father[tb] = ta;
}
rep (i, 1, n)
{
int cnt = get_father (i);
num[cnt].push_back (a[i]);
pos[cnt].push_back (i);
}
rep (i, 1, n)
{
sort (num[i].begin (), num[i].end (), cmp);
if (num[i].size () > 0)
rep (j, 0, num[i].size () - 1)
ans[pos[i][j]] = num[i][j];
}
rep (i, 1, n - 1)
printf ("%d ", ans[i]);
printf ("%d\n", ans[n]);
return 0;
}