1. 程式人生 > 實用技巧 >聯賽模擬測試23 D. 真相 思維題

聯賽模擬測試23 D. 真相 思維題

題目描述



分析


最後判斷時,我們把所有 \(k\) 相等的說第一類話的人放在一個集合
判斷這些人說真話時得到的結果是否等於 \(k\) 即可,此時另外的人一定都說假話

程式碼

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#define rg register
const int maxn=1e6+5,maxm=1e3+5;
int t,n,h[maxn],tot=1,val[maxn],sta[maxn],tp,js,allfake,tj[maxn][2],jl,jud2;
bool vis[maxn];
char s[maxm];
struct asd{
	int to,nxt,val;
}b[maxn];
void ad(int aa,int bb,int cc){
	b[tot].to=bb;
	b[tot].nxt=h[aa];
	b[tot].val=cc;
	h[aa]=tot++;
}
void dfs(int now,int fa,int lat){
	if(lat==1) js++;
	for(rg int i=h[now];i!=-1;i=b[i].nxt){
		rg int u=b[i].to;
		if(u==fa) continue;
		if(lat==1) dfs(u,now,b[i].val);
		else dfs(u,now,b[i].val^1);
	}
}
void dfs2(int now,int fa,int lat){
	if(now==n){
		jl=lat;
		return;
	}
	for(rg int i=h[now];i!=-1;i=b[i].nxt){
		rg int u=b[i].to;
		if(u==fa) continue;
		if(lat==1) dfs2(u,now,b[i].val);
		else dfs2(u,now,b[i].val^1);
	}
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		tot=1;
		tp=allfake=0;
		for(rg int i=0;i<=n;i++){
			h[i]=-1;
			val[i]=0;
			vis[i]=0;
		}
		rg int haha;
		rg bool jud=0;
		for(rg int i=1;i<=n;i++){
			scanf("%s",s+1);
			haha=i+1;
			if(haha>n) haha-=n;
			if(s[1]=='+'){
				ad(haha,i,1);
				ad(i,haha,1);
			} else if(s[1]=='-'){
				ad(haha,i,0);
				ad(i,haha,0);
			} else {
				scanf("%d",&val[i]);
				sta[++tp]=i;
			}
		}
		for(rg int i=1;i<=n;i++){
			tj[val[i]][0]=tj[val[i]][1]=0;
		}
		if(tp==0){
			jl=1;
			dfs2(1,0,1);
			if((b[tot-2].val^jl)==0) jud=1;
		} else {
			for(rg int i=1;i<=tp;i++){
				js=0;
				vis[val[sta[i]]]=1;
				dfs(sta[i],0,0);
				allfake+=js;
				tj[val[sta[i]]][0]+=js;
				js=0;
				dfs(sta[i],0,1);
				tj[val[sta[i]]][1]+=js;
			}
			for(rg int i=1;i<=tp;i++){
				if(allfake-tj[val[sta[i]]][0]+tj[val[sta[i]]][1]==val[sta[i]]) jud=1;
			}
			if(vis[allfake]==0) jud=1;
		}
		if(!jud) printf("inconsistent\n");
		else printf("consistent\n");
	}
	return 0;
}