信友队集训 D12T1 找数列

Link\text{Link}

题意

一个矩阵 BB01 矩阵,有 mm 个位置的值给定,其余位置任意。问是否存在数组 A1nA_{1\sim n} 使得对任意给定值的位置 Bi,jB_{i,j} ,都有 Bi,j=AiAjB_{i,j}=|A_i-A_j|

分析

由于 BB01 矩阵,所以任意一对 Ai,AjA_i,A_j 之差不超过 11 ,那么我们不妨设 A1nA_{1\sim n} 全为 1100 ,那么 BB 矩阵表述的关系可以转化为异或:

Bi,j=1AiAj=1B_{i,j}=1\Longleftrightarrow A_i\oplus A_j=1 Bi,j=0AiAj=0B_{i,j}=0\Longleftrightarrow A_i\oplus A_j=0

于是把确定的 Bi,jB_{i,j} 当成一条连着 i,ji,j 的双向边,对这张图进行染色,看是否有矛盾即可。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int N=1e5+10;
int n,m,t,vis[N],col[N];
int head[N],ver[N<<1],nxt[N<<1],edge[N<<1],tot;
void add(int x,int y,int z){
	ver[++tot]=y;
	edge[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
bool dfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		int y=ver[i],z=edge[i];
		if(!vis[y]){
			col[y]=col[x]^z;
			if(dfs(y))
				return 1;
		}
		else if(col[x]^z!=col[y])
				return 1;
	}
	return 0;
}
int main(){
	t=read();
	while(t--){
		n=read();m=read();
		for(int i=1;i<=n;i++)
			head[i]=vis[i]=col[i]=0;
		tot=0;
		for(int i=1;i<=m;i++){
			int x,y,z;
			x=read();y=read();z=read();
			add(x,y,z);add(y,x,z);
		}
		bool f=0;
		for(int i=1;i<=n;i++){
			if(!vis[i])
				if(dfs(i)){
					f=1;
					break;
				}
		}
		if(f)
			puts("no");
		else puts("yes");
	}
	return 0;
}
posted @ 2023-07-29 15:05  luckydrawbox  阅读(13)  评论(0)    收藏  举报  来源