Loading

【题解】CF1697F-Too Many Constraints

构造一个长度为 \(n\) 的不降序列 \(a\),满足 \(a_i\in[1,k]\),并且满足若干个形如 \(a_i\neq x,a_i+a_j \le x,a_i+a_j \ge x\) 的条件。

观察到 \(k\) 非常小,考虑拆点的图论建模。

把每个点拆成 \(k\) 个点,然后跑 2-SAT 模型。\(p_{i,j}\) 为真表示 \(a_i = j\),然后将条件连边即可。

但是这么做无法构造方案。因为这样建模,每个点拆出的 \(k\) 个点中,至少要恰好有一个点为真,但是 2-SAT 模型只能保证最多一个点为真。

考虑构造另外一种方式,我们进行前缀转化,其中 \(p_{i,j}\) 为真表示 \(a_i \ge j\),那么每个点拆出的 \(k\) 个点,一定是前面一段为真,后面一段为假,这个条件可以简单处理。然后再把输入的限制连边即可。时间复杂度 \(\mathcal{O}(nk^2)\)

#define N 400005
#define M 20005
#define S 20000005
int n, m, k, idx, id[M][11][2], tot, h[N], num, top, cnt, sta[N], v[N], dfn[N], low[N], col[N];
struct edge{int to, nxt;}e[S];
void add(int x,int y){e[++tot].nxt = h[x], h[x] = tot, e[tot].to = y;}
void dfs(int x){
	dfn[x] = low[x] = ++idx, v[sta[++top] = x] = 1;
	for(int i = h[x]; i; i = e[i].nxt){
		int y = e[i].to;
		if(!dfn[y])dfs(y), cmn(low[x], low[y]);
		else if(v[y])cmn(low[x], dfn[y]);
	}
	if(dfn[x] == low[x]){
		++cnt; 
		while(true){
			int y = sta[top--];
			v[y] = 0, col[y] = cnt;
			if(x == y)break;
		}
	}
}
void solve(){
	read(n, m, k), idx = tot = num = cnt = 0;
	rp(i, n)rp(j, k)rep(t, 0, 1)id[i][j][t] = ++num;
	rp(i, num)dfn[i] = low[i] = col[i] = h[i] = 0;
	rp(i, n){
		rp(x, k - 1)add(id[i][x][0], id[i][x + 1][0]), add(id[i][x + 1][1], id[i][x][1]);
		if(i < n)rp(x, k)add(id[i][x][1], id[i + 1][x][1]), add(id[i + 1][x][0], id[i][x][0]);
		add(id[i][1][0], id[i][1][1]);
	}
	while(m--){
		int op, x, y, z;
		read(op, x, y);
		if(1 == op){
			if(y == k)add(id[x][y][1], id[x][y][0]);
			else add(id[x][y][1], id[x][y + 1][1]), add(id[x][y + 1][0], id[x][y][0]);
		}
		else {
			read(z);
			if(2 == op){
				rp(l, k)rp(r, k)if(l + r > z){
					if(l > z)add(id[x][l][1], id[x][l][0]);
					if(r > z)add(id[y][r][1], id[y][r][0]);
					add(id[x][l][1], id[y][r][0]), add(id[y][r][1], id[x][l][0]);
				}
			}
			else{
				rp(l, k)rp(r, k){
					if(l + k - 1 < z)add(id[x][l][0], id[x][l][1]);
					if(r + k - 1 < z)add(id[y][r][0], id[y][r][1]);
					if(l + r - 1 <= z)
						add(id[x][l][0], id[y][r][1]), add(id[y][r][0], id[x][l][1]);
				}
			}
		}
	}
	rp(i, num)if(!dfn[i])dfs(i);
	rp(i, n)rp(j, k)if(col[id[i][j][0]] == col[id[i][j][1]]){puts("-1"); return;}
	rp(i, n)pr(j, k)if(col[id[i][j][0]] > col[id[i][j][1]]){printf("%d ", j); break;}
	el;
}
int main() {int T; read(T); while(T--)solve();}
posted @ 2022-06-14 11:38  7KByte  阅读(108)  评论(0编辑  收藏  举报