小Q的变换
时间限制: 1 Sec 内存限制: 128 MB题目描述
给定一个1到n的某个排列p和一个变换矩阵,现在可以根据这个变换矩阵交换排列中一对或⼏对元素的位置,可以交换无数次,问这样得到的字典序最小的排列是哪一个。1到n的排列是一个含n个数字的数列,其中1到n各个数字都恰好出现一次。
变换矩阵是一个n*n的01矩阵,其中的元素只有0和1。如果第i行第j列是1,则表示排列中第i个元素和第j个元素这一对能交换位置。如果是0,则不能交换位置。保证该矩阵关于沿左上到右下的对角线对称。
字典序最小是指使得小的数字尽可能的在前面,⼤的数字尽可能在后面。如12345的字典序比12354更小。
输入
第一行输入1个数字n,表示是1到n的排列。第二行n个数字,依次表示排列p中的数。
第3到n+2行,每行n个字符,形成n*n的变换矩阵。(只可能出现0/1)
输出
输出一行n个数字,表示你的答案。样例输入
5 4 2 1 5 3 00100 00011 10010 01101 01010
样例输出
1 2 3 4 5
提示
对于30%数据,1≤n≤10对于60%数据,1≤n≤50
对于100%数据,1≤n≤300
题解
用并查集分为几个联通块,每个联通块内进行排序。
1 #include<vector> 2 #include<cstdio> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int n,a[330],f[330],b[330]; 7 char c[330][330]; 8 vector<int>g[330]; 9 int _find(int x) 10 { 11 if(f[x]!=x) 12 f[x]=_find(f[x]); 13 return f[x]; 14 } 15 int main() 16 { 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++) 19 f[i]=i; 20 for(int i=1;i<=n;i++) 21 scanf("%d",&a[i]); 22 for(int i=1;i<=n;i++) 23 scanf("%s",c[i]+1); 24 for(int i=1;i<=n;i++) 25 for(int j=i+1;j<=n;j++) 26 { 27 if(c[i][j]!='1') 28 continue; 29 int fi=_find(i); 30 int fj=_find(j); 31 f[fj]=f[fi]; 32 } 33 for(int i=1;i<=n;i++) 34 { 35 int fi=_find(i); 36 g[fi].push_back(a[i]); 37 } 38 for(int i=1;i<=n;i++) 39 { 40 if(f[i]!=i) 41 continue; 42 sort(g[i].begin(),g[i].end()); 43 int t=0; 44 for(int j=1;j<=n;j++) 45 if(f[j]==i) 46 b[j]=g[i][t++]; 47 } 48 for(int i=1;i<n;i++) 49 printf("%d ",b[i]); 50 printf("%d\n",b[n]); 51 return 0; 52 }View Code
标签:数字,变换,矩阵,330,int,include 来源: https://www.cnblogs.com/Jony-English/p/12201213.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。