题意:
题意:有一排 $n$ 个灯,可以是红色或者蓝色,然后k个人投票,每个人投的票会写上他猜测的某三盏灯的颜色。然后现在问是否有一种红蓝灯的安排方式使得每个人投的票至少有2个猜测是对的。
题解:
$2-SAT$ 板子题,但是比赛时候忘记了(主要这东西在中国真的很少考emm)相当于求让每个人的条件都为真的一组二进制向量。那么现在的问题就是怎么把每个人的约束条件转化为 $2-SAT$ 的子句的形式。
首先用 $x_1$ $x_2$ $x_3$ 表示一个人的三个选择,那么代表这个人的子句用文字表达来说就是 $x_1 x_2 x_3$ 中有2个或者3个为真。用条件的知识可以推出来这个说法等价于 $(x_1\lor x_2 )\land(x_1\lor x_3)\land(x_2\lor x_3)$ ,这样就把每个人的条件写成 $2-SAT$ 的形式了,接下来按板子连通分量+拓扑排序求解就OK了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 7;
const int maxm=4e5+10;
const int mod = 1e9 + 7;
struct {
int to,next;
}edge[maxm];
int head[maxn],tot;
void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v){
edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];
int index,top;
int scc;
bool instack[maxn];
int num[maxn];
void Tarjan(int u){
int v;
low[u]=dfn[u]=++index;
Stack[top++]=u;
instack[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(instack[v]&&low[u]>dfn[v]){
low[u]=dfn[v];
}
}
if(low[u]==dfn[u]){
++scc;
do{
v=Stack[--top];
instack[v]=false;
belong[v]=scc;
num[scc]++;
}while(v!=u);
}
}
bool solvable(int n){
memset(dfn,0,sizeof(dfn));
memset(instack,false,sizeof(instack));
memset(num,0,sizeof(num));
index=scc=top=0;
for(int i=0;i<n;++i) if(!dfn[i]) Tarjan(i);
for(int i=0;i<n;i+=2) if(belong[i]==belong[i^1]) return false;
return true;
}
queue<int> q1,q2;
vector<vector<int> >dag;
char color[maxn];
int indeg[maxn];
int cf[maxn];
void solve(int n){
dag.assign(scc+1,vector<int>());
memset(indeg,0,sizeof(indeg));
memset(color,0,sizeof(color));
for(int u=0;u<n;++u)
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(belong[u]!=belong[v]){
dag[belong[v]].push_back(belong[u]);
indeg[belong[u]]++;
}
}
for(int i=0;i<n;i+=2){
cf[belong[i]]=belong[i^1];
cf[belong[i^1]]=belong[i];
}
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
for(int i=1;i<=scc;++i) if(indeg[i]==0) q1.push(i);
while(!q1.empty()){
int u=q1.front();
q1.pop();
if(color[u]==0){
color[u]='R';
color[cf[u]]='B';
}
int sz=dag[u].size();
for(int i=0;i<sz;++i){
indeg[dag[u][i]]--;
if(indeg[dag[u][i]]==0)
q1.push(dag[u][i]);
}
}
}
int idx(int x,int op){//R 2*x B 2*x+1
if(op==0) return 2*x;
return 2*x+1;
}
void addcond(int x1,int op1,int x2,int op2){
addedge(idx(x1,op1^1),idx(x2,op2));
addedge(idx(x2,op2^1),idx(x1,op1));
}
int main() {
int k,n,x1,x2,x3,op1,op2,op3;
char o1,o2,o3;
scanf("%d%d",&k,&n);
init();
for(int i=1;i<=n;++i){
scanf(" %d %c %d %c %d %c",&x1,&o1,&x2,&o2,&x3,&o3);
op1=(o1=='R'?0:1);
op2=(o2=='R'?0:1);
op3=(o3=='R'?0:1);
x1--,x2--,x3--;
addcond(x1,op1,x2,op2);
addcond(x1,op1,x3,op3);
addcond(x2,op2,x3,op3);
}
if(solvable(2*k)){
solve(2*k);
for(int i=0;i<k;++i){
if(color[belong[2*i]]=='R')printf("R");
else printf("B");
}
}
else{
puts("-1");
}
return 0;
}
/*
7 5
3 R 5 R 6 B
1 B 2 B 3 R
4 R 5 B 6 B
5 R 6 B 7 B
1 R 2 R 4 R
*/
