[CF1343F] Restore the Permutation by Sorted Segments【构造】

首先有一个观察:由于 \(k_i>1\),因此除了位置 \(1\)\(n\) 的数,其余的数都出现了至少 \(2\) 次。

考虑从 \(n\)\(1\) 逐位确定,假设当前处理到第 \(m\) 位,会有以下几种情况:

  • 在未被占据的区间中,只有一个数 \(x\) 出现了 \(1\) 次;

这种情况下,显然只能选择 \(x\) 作为第 \(m\) 位。

  • 有两个数 \(x, y\) 出现了 \(1\) 次,但 \(x\) 出现的区间长度 \(\geq 3\)

由于位置 \(1\) 的数必然会出现在 \([1, 2]\) 中,因此 \(x\) 只能在位置 \(m\) 出现。

  • 有两个数 \(x, y\) 出现了 \(1\) 次,且出现的区间长度均 \(=2\)

这时候我们无法直接判断谁出现在第 \(m\) 位,因此可以直接枚举并 dfs,直到找到一组合法解为止。

乍一看这样的复杂度是指数级别的,但是注意到还有另外一个条件:若存在 \(k>m\),满足 \(k\) 出现的区间覆盖了位置 \(m\),那么 \(m\) 上的数必须在 \(k\) 出现的区间里。因此,如果我们在上一步中选择了向下 dfs,那么这一步实际上只有一个可能的数字(即上一步选择的区间覆盖的另一个元素),因此每到达一个分叉点后,都不会再出现新的分叉点,每一步中即使 \(O(n)\) 判断是否合法,实际复杂度也只有 \(O(n^3)\) 级别。

Code:

#include <bits/stdc++.h>
#define R register
#define mp make_pair
#define ll long long
#define pii pair<int, int>
using namespace std;
const int mod = 998244353, N = 210;

int t, n, ans[N], bel[N];
vector<int> seg[N];
set<int> app[N];

inline int addMod(int a, int b) {
	return (a += b) >= mod ? a - mod : a;
}

inline ll quickpow(ll base, ll pw) {
	ll ret = 1;
	while (pw) {
		if (pw & 1) ret = ret * base % mod;
		base = base * base % mod, pw >>= 1;
	}
	return ret;
}

template <class T>
inline void read(T &x) {
	x = 0;
	char ch = getchar(), w = 0;
	while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
	while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	x = w ? -x : x;
	return;
}

int dfs(int m) {
	int vis[N];
	for (R int i = 1; i <= n; ++i) vis[i] = 0;
	int num = 0;
	for (R int i = m + 1; i <= n; ++i) {
		if ((int) seg[bel[i]].size() <= i - m) continue;
		++num, --vis[ans[i]];
		for (auto &v : seg[bel[i]]) ++vis[v];
	}
	if (m == 1) {
		for (R int i = 1; i <= n; ++i)
			if (vis[i] == num) return ans[1] = i, 1;
		return 0;
	}
	pii s(0, 0);
	for (R int i = 1; i <= n; ++i) {
		if (vis[i] != num || app[i].size() != 1) continue;
		(s.first ? s.second : s.first) = i;
	}
	if (!s.first) return 0;
	if (s.second && seg[*app[s.first].begin()].size() < seg[*app[s.second].begin()].size())
		swap(s.first, s.second);
	if (s.second && seg[*app[s.first].begin()].size() == 2) {
		int w = *app[s.second].begin(), flag = 1;
		for (auto &v : seg[w])
			if (!app[v].size()) flag = 0;
		if (flag) {
			ans[m] = s.second, bel[m] = w;
			for (auto &v : seg[w]) app[v].erase(w);
			if (dfs(m - 1)) return 1;
			for (auto &v : seg[w]) app[v].insert(w);
		}
	}
	int w = *app[s.first].begin();
	for (auto &v : seg[w])
		if (!app[v].size()) return 0;
	ans[m] = s.first, bel[m] = w;
	for (auto &v : seg[w]) app[v].erase(w);
	if (dfs(m - 1)) return 1;
	for (auto &v : seg[w]) app[v].insert(w);
	return 0;
}

int main() {
	int x, y;
	read(t);
	while (t--) {
		read(n);
		for (R int i = 1; i < n; ++i) {
			read(x), seg[i].clear();
			while (x--) {
				read(y), seg[i].push_back(y);
				app[y].insert(i);
			}
		}
		dfs(n);
		for (R int i = 1; i <= n; ++i)
			printf("%d ", ans[i]);
		printf("\n");
	}
	return 0;
}
posted @ 2020-04-26 15:45  suwakow  阅读(322)  评论(0编辑  收藏  举报
Live2D