【题解】CF500B:New Year Permutation

原题传送门
怎么说呢,输入就需要 O ( n 2 ) O(n^2) O(n2)的题目有点那个了。。
祭出一个基础算法——并查集!!!

仿照缩点(强连通分量)的想法,如果一个点的集合,对于集合中的每一个点都能找到另一个集合中的点可以与之交换
那么这个点的集合可看成一个点,用并查集维护一下连通性
对于每一个位置,找当下 ( v i s = 0 ) (vis=0) (vis=0)最小的并且与这个位置联通的点输出

Code:

#include <bits/stdc++.h>
#define maxn 310
using namespace std;
struct data{
	int x, id;
}a[maxn];
int f[maxn], vis[maxn], n;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

bool cmp(data x, data y){ return x.x < y.x; }
int getf(int k){ return k == f[k] ? k : f[k] = getf(f[k]); }

int get(){
	char c = getchar();
	for (; c != '0' && c != '1'; c = getchar());
	return c == '1';
}

void Union(int i, int j){
	int x = getf(i), y = getf(j);
	if (x != y) f[x] = y;
}

int main(){
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = (data){read(), i}, f[i] = i;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (get()) Union(i, j);
	sort(a + 1, a + 1 + n, cmp);
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (!vis[a[j].id] && getf(i) == getf(a[j].id)){
				vis[a[j].id] = 1, printf("%d ", a[j].x); break;
			}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值