聯賽模擬測試23 D. 真相 思維題
阿新 • • 發佈:2020-10-26
題目描述
分析
最後判斷時,我們把所有 \(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; }