QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#604067#7798. Colorful Villagesurgutti#WA 1ms3888kbC++204.1kb2024-10-01 22:52:072024-10-01 22:52:09

Judging History

你现在查看的是最新测评结果

  • [2024-10-01 22:52:09]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3888kb
  • [2024-10-01 22:52:07]
  • 提交

answer

// Author: Olaf Surgut (surgutti)
// Created on 01-10-2024 15:58:20
#include <bits/stdc++.h>
using namespace std;

#ifdef DEBUG
auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";}
auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";}
#define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X)
#else
#define debug(...){}
#endif

#define endl '\n'
#define st first
#define nd second
#define pb push_bask
#define eb emplace_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define ROF(i, b, a) for (int i = (b); i >= (a); i--)
#define REP(i, n) for (int i = 0; i < (n); i++)

#include <vector>
#include <cassert>

struct SAT {
	int n;
	std::vector<std::vector<int>> adj;
	std::vector<int> ans;
	
private:
	std::vector<int> val, comp, z; int time = 0;
	int dfs(int u) {
	int low = val[u] = ++time, x; z.push_back(u);
		for(int v : adj[u]) if(!comp[v])
			low = std::min(low, val[v] ?: dfs(v));
		if(low == val[u]) do {
			x = z.back(); z.pop_back();
			comp[x] = low;
			if(ans[x >> 1] == -1) ans[x >> 1] = x & 1;
		} while(x != u);
		return val[u] = low;
	}
public:
	SAT(int _n) : n(_n), adj(2 * n) { }
	
	void either(int a, int b) { // zoga_mother.either(zoga, ~myszojelen);
		a = std::max(2 * a, -1 - 2 * a);
		b = std::max(2 * b, -1 - 2 * b);
		debug(a, b, 2 * n);
		assert(0 <= a && a < 2 * n && 0 <= b && b < 2 * n);
		adj[a].push_back(b ^ 1);
		adj[b].push_back(a ^ 1);
	}
	
	void set_value(int x) { either(x, x); }
	
	bool solve() {
		ans.assign(n, -1);
		val.assign(2 * n, 0); comp = val;
		for(int i = 0; i < 2 * n; i++)	if(!comp[i])	dfs(i);
		for(int i = 0; i < n; i++)	if(comp[i << 1] == comp[i << 1 | 1])	
			return false;
		return true;
	}
};

const int N = 200000 + 7;

int n, c[N];
vector<int> adj[N];
int pre[N], pos[N], czas;

void dfs(int u, int f) {
	pre[u] = ++czas;
	debug("pre", u, czas);
	for (int v : adj[u]) if (v != f) {
		dfs(v, u);
	}
	pos[u] = czas;
}

bool is_anc(int u, int v) {
	return pre[u] <= pre[v] && pos[v] <= pos[u];
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int tt;
	cin >> tt;
	while (tt--) {
		cin >> n;
		map<int, int> S;
		FOR(i, 1, 2 * n) {
			cin >> c[i];

			if (S.count(c[i])) {
				c[i] = ~c[i];
			}

			assert(S.count(c[i]) == 0);
			S[c[i]] = i;
		}

		FOR(i, 1, 2 * n - 1) {
			int u, v;
			cin >> u >> v;

			adj[u].push_back(v);
			adj[v].push_back(u);
		}

		czas = 0;
		dfs(1, 0);

		vector<pair<int, int>> sat;
	
		int tree_size = 1;
		while (tree_size <= 2 * n)
			tree_size <<= 1;

		int tree_offset = n + 1;

		auto add = [&](int l, int r, int x) {
			debug(l, r, x);
			for (l += tree_size, r += tree_size + 1; l < r; l >>= 1, r >>= 1) {
				if (l & 1) {
					sat.eb(~(tree_offset + l), x);
					l++;
				}

				if (r & 1) {
					r--;
					sat.eb(~(tree_offset + r), x);
				}
			}
		};

		FOR(i, 1, tree_size - 1) {
			sat.eb(tree_offset + i, ~(tree_offset + 2 * i + 0));
			sat.eb(tree_offset + i, ~(tree_offset + 2 * i + 1));
		}

		FOR(i, 1, 2 * n) {
			debug(tree_offset + tree_size + pre[i]);
			sat.eb(~c[i], tree_offset + tree_size + pre[i]);
		}

		FOR(i, 1, n) {
			int a = S[i];
			int b = S[~i];

			if (is_anc(a, b)) {
				add(1, pre[a] - 1, i);
				add(pos[a] + 1, n, i);
			}
			else {
				add(pre[a], pos[a], i);
			}
			
			if (is_anc(b, a)) {
				add(1, pre[b] - 1, ~i);
				add(pos[b] + 1, n, ~i);
			}
			else {
				add(pre[b], pos[b], ~i);
			}
		}

		SAT krowa(9 * n + 1);
		for (auto [i, j] : sat) {
			krowa.either(i, j);
		}

		if (krowa.solve()) {
			debug(krowa.ans);
			
			FOR(i, 1, tree_size * 2 - 1) {
				debug(i, krowa.ans[tree_offset + i]);
			}

			FOR(i, 1, n) {
				if (krowa.ans[i]) {
					cout << S[i] << ' ';
				}
				else {
					cout << S[~i] << ' ';
				}
			}
			cout << '\n';
		}
		else {
			cout << "-1\n";
		}

		sat.clear();
		FOR(i, 1, 2 * n)
			adj[i].clear();
	}

	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3656kb

input:

2
4
1 3 1 3 4 4 2 2
1 6
5 3
2 4
7 1
7 5
5 8
2 5
3
1 1 2 2 3 3
1 2
2 3
3 4
4 5
5 6

output:

3 7 2 5 
-1

result:

ok ok, 1 yes, 1 no (2 test cases)

Test #2:

score: 0
Accepted
time: 1ms
memory: 3888kb

input:

1
1
1 1
1 2

output:

2 

result:

ok ok, 1 yes, 0 no (1 test case)

Test #3:

score: -100
Wrong Answer
time: 1ms
memory: 3560kb

input:

5
1
1 1
2 1
1
1 1
2 1
3
3 2 3 1 1 2
4 1
6 1
3 5
5 1
2 4
4
3 3 1 1 4 4 2 2
2 7
7 6
1 2
8 1
4 2
2 5
3 1
1
1 1
1 2

output:

2 
2 
5 6 1 
4 8 2 5 
2 

result:

wrong answer subtree not connected: only 2 edges for 4 vertices (test case 4)