题目链接:OnlineJudge
思路:我们把可以交换的两个位置放入一个连通块,经过这样的处理后我们发现在一个连通块的数可以随意互换位置,而不在一个连通块内的数则不能进行位置交换,所以为了使得最后的排列方式字典序最小,我们只要把每个连通块内的数按照字典序从小到大进行排序即可
下面是代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e6+10;
int fu[N],a[N];
typedef pair<int,int>PII;
priority_queue<int,vector<int>,greater<int> > q[N];
int find(int x)
{
if(fu[x]!=x) fu[x]=find(fu[x]);
return fu[x];
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
fu[i]=i;
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)//把所有位置分成不同的连通块
{
int u,v;
scanf("%d%d",&u,&v);
int f1=find(u),f2=find(v);
if(f1==f2) continue;
fu[f1]=f2;
}
for(int i=1;i<=n;i++)//把对应位置元素值放入对应连通块中
q[find(i)].push(a[i]);
for(int i=1;i<=n;i++)//每次输出当前位置连通块中最小值,等同于在连通块内部进行排序
{
int f=find(i);
printf("%d ",q[f].top());
q[f].pop();
}
return 0;
}