题意:
给你一个长度为n的数列,然后给你m组数,
表示这两个数可以交换
然后让你给出字典序最大的数列
思路:
用并查集,可交换的数都是成组的,把同一并查集中的数加在根节点的vector后,
在一个并查集中的数,从大到输出就好了
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int N=1e6+10; int a[N],pre[N],cnt[N]; vector<int>eg[N]; int find(int x)//查找根节点 { int r=x; while(pre[r]!=r)//返回根节点r r=pre[r]; int i=x,j; while(i!=r)//路径压缩 { j=pre[i];//在改变上级之前用临时变量j记录下他的值 pre[i]=r;//把上级改为根节点 i=j; } return r; } void join(int x,int y)//判断x,y是否连通.如果已经连通,就不用管了;如果不连通,就把它们所在的连通分支合并起 { int fx=find(x),fy=find(y); if(fx!=fy) pre[fx]=fy; } int main() { //freopen("in.txt","r",stdin); int n,m,x,y; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&a[i]); a[i]--; pre[i]=i; } while(m--) { scanf("%d%d",&x,&y); join(--x,--y); } for(int i=0;i<n;i++) eg[find(i)].push_back(a[i]); for(int i=0;i<n;i++) { if(eg[i].empty()) continue; sort(eg[i].begin(),eg[i].end(),greater<int>()); } for(int i=0;i<n;i++) printf("%d ",eg[find(i)][cnt[find(i)]++]+1); return 0; }