CF1697F

考虑 2-SAT,如果设 \((i,j,0/1)\) 表示 \(a_i\) 是否等于 \(j\) 则需要 \((i,1,1),\dots,(i,k,1)\) 中某一个被选,2-SAT 很难处理,于是设 \((i,j,0/1)\) 表示 \(a_i\) 是否大于等于 \(j\),最后找任意一个合法的即可。
由于边界上有可能会出现问题,所以我们可以加上 \(0\)\(k+1\) 来方便操作。
1.本身含义
\((i,j,1)\rightarrow(i,j-1,1),(i,j-1,0)\rightarrow(i,j,0),(i,0,0)\rightarrow(i,0,1),(i,1,0)\rightarrow(i,1,1),(i,k+1,1)\rightarrow(i,k+1,0)\)
2.单调要求
\((i,j,1)\rightarrow(i+1,j,1),(i+1,j,0)\rightarrow(i,j,0)\)
3.\(a_i\neq j\)
\(j=k\),则 \((i,j,1)\rightarrow(i,j,0)\)
否则,\((i,j,1)\rightarrow(i,j+1,1),(i,j+1,0)\rightarrow(i,j,0)\)
4.\(a_i+a_j\le x\)
\(a_i\ge w\),则 \(a_j\le x-w\)
\(v\le w,a_j\le x-w\),则 \(a_j\le x-v\)
所以只需要考虑 \(a_j\le x-w\)
于是 \(x-w\ge k\) 时直接忽略,\(1\le x-w\)\((i,w,1)\rightarrow(j,x-w+1,0)\),否则类似第 3 类操作。
反向同理。
5.\(a_i+a_j\ge x\)
\(a_i\le w\),则 \(a_j\ge x-w\)
\(v\ge w,a_j\ge x-w\),则 \(a_j\ge x-v\)
所以只需要考虑 \(a_j\ge x-w\).
于是 \(x-w\le 1\) 时直接忽略,\(x-w\le k\)\((i,w+1,0)\rightarrow(j,x-w,1)\) ,否则类似第 3 类操作。
反向同理。

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(r);i>=(l);i--)
#define pb push_back
#define clr clear
using namespace std;
const int N=1e6+5;
int n,m,k;
int f(int x,int y,int z){
	return n*(k+2)*z+(x-1)*(k+2)+(y+1);
}
vector<int>g[N];
void makeneq(int pos,int val){
	if(1<=val&&val<=k){
		g[f(pos,val,1)].pb(f(pos,val+1,1));
		g[f(pos,val+1,0)].pb(f(pos,val,0));
	}
}
int dfn[N],low[N],Tim;
int stk[N],top;
bitset<N>mk;
int col[N],idx;
void tarjan(int u){
	dfn[u]=low[u]=++Tim;
	stk[++top]=u;
	mk[u]=1;
	for(auto v:g[u]){
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(mk[v]){
			low[u]=min(low[u],low[v]);
		}
	}
	if(dfn[u]==low[u]){
		idx++;
		while(stk[top]!=u){
			col[stk[top]]=idx;
			mk[stk[top]]=0;
			top--;
		}
		col[u]=idx;
		mk[u]=0;
		top--;
	}
}
bool cmp(int x,int y){
	return x>y;
}
void slv(){
	scanf("%d %d %d",&n,&m,&k);
	int nds=f(n,k+1,1);
	rep(i,1,nds){
		g[i].clr();
	}
	rep(i,1,n){
		rep(j,0,k){
			g[f(i,j,0)].pb(f(i,j+1,0));
			g[f(i,j+1,1)].pb(f(i,j,1));
		}
		g[f(i,0,0)].pb(f(i,0,1));
		g[f(i,1,0)].pb(f(i,1,1));
		g[f(i,k+1,1)].pb(f(i,k+1,0));
	}
	rep(i,1,n-1){
		rep(j,1,k){
			g[f(i,j,1)].pb(f(i+1,j,1));
			g[f(i+1,j,0)].pb(f(i,j,0));
		}
	}
	while(m--){
		int op;
		scanf("%d",&op);
		if(op==1){
			int pos,val;
			scanf("%d %d",&pos,&val);
			makeneq(pos,val);
		}
		if(op==2){
			int x,y,val;
			scanf("%d %d %d",&x,&y,&val);
			rep(w,1,k){
				if(w>=val){
					makeneq(x,w);
				}
				else if(w+k>val){
					g[f(x,w,1)].pb(f(y,val-w+1,0));
					g[f(y,val-w+1,1)].pb(f(x,w,0));
				}
			}
			swap(x,y);
			rep(w,1,k){
				if(w>=val){
					makeneq(x,w);
				}
				else if(w+k>val){
					g[f(x,w,1)].pb(f(y,val-w+1,0));
					g[f(y,val-w+1,1)].pb(f(x,w,0));
				}
			}
		}
		if(op==3){
			int x,y,val;
			scanf("%d %d %d",&x,&y,&val);
			rep(w,1,k){
				if(w+k<val){
					makeneq(x,w);
				}
				else if(w<val-1){
					g[f(x,w+1,0)].pb(f(y,val-w,1));
					g[f(y,val-w,0)].pb(f(x,w+1,1));
				}
			}
			swap(x,y);
			rep(w,1,k){
				if(w+k<val){
					makeneq(x,w);
				}
				else if(w<val-1){
					g[f(x,w+1,0)].pb(f(y,val-w,1));
					g[f(y,val-w,0)].pb(f(x,w+1,1));
				}
			}
		}
	}
	Tim=0;
	mk=0;
	idx=0;
	rep(i,1,nds){
		dfn[i]=0;
		low[i]=0;
		sort(g[i].begin(),g[i].end(),cmp);
	}
	per(i,1,nds){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	rep(i,1,n){
		bool fd=0;
		rep(j,1,k){
			if(col[f(i,j,0)]==col[f(i,j,1)]){
				printf("-1\n");
				return ;
			}
			if(col[f(i,j,1)]<col[f(i,j,0)]){
				fd=1;
			}
		}
		if(!fd){
			printf("-1\n");
			return ;
		}
	}
	rep(i,1,n){
		per(j,1,k){
			if(col[f(i,j,1)]<col[f(i,j,0)]){
				printf("%d ",j);
				break;
			}
		}
	}
	putchar('\n');
}
int main(){
	int T=1;
	scanf("%d",&T);
	while(T--)slv();
	return 0;
}
posted @ 2024-08-07 21:02  ax_by_c  阅读(16)  评论(0)    收藏  举报