Gym 101987KTV Show Game(2-SAT)
Posted cherish-lin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym 101987KTV Show Game(2-SAT)相关的知识,希望对你有一定的参考价值。
题目链接:https://vj.z180.cn/b4aacc08fc7aab6ce14e7baf13816c24?v=1571542994
题目要求n个灯(R,B),给出m组赋值方式,每一组中至少有两个是正确的,问是否能找到一组正确的赋值方式.
2-SAT模板运用强连通分量解决此类真值指派问题.
对于一组赋值: a x b y c z 来说
若a假,则bc为真
若b假,则ac为真
若c假,则ab为真
建边跑SCC(强连通分量即可)
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e6 + 5; const int inf = 0x3f3f3f3f; int dfn[maxn],low[maxn],head[maxn],belong[maxn]; //dfs序编号,最早能访问到的祖先编号,belong[i]代表i属于哪一个强连通分量 int num[maxn];//num[i]代表i这个强连通分量中有多少个元素 stack<int>sta; int dfs_clock,cnt,scc_cnt,n,m;//DFS中的编号,边的编号,强连通分量的编号 struct node { int v,next; }e[maxn]; void add(int u,int v) { e[cnt]=(node){v,head[u]}; head[u]=cnt++; } void DFS(int u) { sta.push(u); low[u]=dfn[u]=++dfs_clock; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ DFS(v); low[u]=min(low[u],low[v]); } else if(!belong[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){//以u为起点的搜索子树是一个强连通分量 scc_cnt++; for(;;){ int now=sta.top(); sta.pop(); belong[now]=scc_cnt; if(now==u)break; } } } int two_sat(){ for(int i = 1;i <= 2 * n;i++){ if(!dfn[i]){ DFS(i); } } for(int i = 1;i <= n;i++){ if(belong[i] == belong[i+n])return 0; } return 1; } int x,y,z,xx,yy,zz; int main(){ ios::sync_with_stdio(0); cin >> n >> m; for(int i = 1;i <= n * 2;i++)head[i] = -1; for(int i = 1;i <= m;i++){ int a,b,c; char s1,s2,s3; cin >> a >> s1 >> b >> s2 >> c >> s3; if(s1 == ‘R‘)x = 1; else x = 0; if(s2 == ‘R‘)y = 1; else y = 0; if(s3 == ‘R‘)z = 1; else z = 0; xx = x ^ 1; yy = y ^ 1; zz = z ^ 1; add(a + xx * n,b + y * n); add(a + xx * n,c + z * n);//a错,bc肯定对 add(b + yy * n,a + x * n); add(b + yy * n,c + z * n);//b错,ac肯定对 add(c + zz * n,a + x * n); add(c + zz * n,b + y * n);//c错,ab肯定对 } int x = two_sat(); if(x){ for(int i = 1;i <= n;i++){ if(belong[i] > belong[i+n])cout << ‘R‘; else cout << ‘B‘; } cout << endl; } else cout << -1 << endl; return 0; }
以上是关于Gym 101987KTV Show Game(2-SAT)的主要内容,如果未能解决你的问题,请参考以下文章
GCD Guessing Game Gym - 100085G 猜数字 gcd
[Gym-101981J] Prime Game (组合计数)