比赛链接:

https://codeforces.com/contest/1715

D. 2+ doors

题意:

长为 \(n\) 的序列,已知 \(q\) 条关系,\(i, j, x\) 表示 \(a_i | a_j = x\),问满足条件的字典序最小的序列是什么。

思路:

如果 \(x\) 某位上为 0,说明这两个位置的数的这一位都是 0。
如果某位为 1,为了让字典序小,肯定要让 0 往前靠。
建立一个图,\(i\)\(j\) 相连边权为 \(x\),如果当前这位为 1,且之前有一位已经是 0 了,那么这一位只能是 1 了,不然就可以是 0。
再考虑一个特殊情况,\(i\)\(j\) 相等的时候,这个位置只能是 \(x\) 了,不会发生改变。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n, q;
	cin >> n >> q;
	vector <int> ans(n + 1, (1 << 30) - 1);
	vector < vector < pair<int, int> > > e(n + 1);
	for (int i = 1; i <= q; i ++ ){
		int u, v, w;
		cin >> u >> v >> w;
		ans[u] &= w;
		ans[v] &= w;
		e[u].push_back({v, w});
		e[v].push_back({u, w});
	}
	for (int u = 1; u <= n; u ++ ){
		for (int j = 0; j < 30; j ++ ){
			if (ans[u] >> j & 1){
				bool ok = false;
				for (auto [v, w] : e[u]){
					if (v == u || !(ans[v] >> j & 1)){
						ok = true;
					}
				}
				if (!ok) ans[u] ^= (1 << j);
			}
		}
		cout << ans[u] << " \n"[u == n];
	}
	return 0;
}
posted on 2022-08-29 17:41  Hamine  阅读(20)  评论(0编辑  收藏  举报