Problem
一群人猜气球,每个人猜三个,每个气球有红蓝两种颜色,求是否存在让每个人至少猜对两个气球的气球颜色方案。
Solution
- 2-sat模板题,场上没往这方面想。
- 2-sat问题解法+证明+模板
- 2-sat解决的什么问题?满足必须满足的约束条件:选了一些必须选另一些。本题中对于一个人来说猜错了某个气球则意味着其它两个气球必须猜对,根据此约束条件建图即可:2i表示第i个气球为红色,2i+1为蓝色,枚举每个人猜错的那个气球建图。
Code
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=5005,maxm=100005;
int k,n,last[maxn*2],cnt,s[maxn*2],c,m;
bool mark[maxn*2];// red 2i blue 2i+1
struct edge{
int v,next;
}e[maxm];
inline void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].next=last[u];
last[u]=cnt;
}
int a1,a2,a3;
char c1,c2,c3;
bool dfs(int x)
{
if(mark[x^1]) return false;
if(mark[x]) return true;
mark[x]=true;
s[c++]=x;
for(int i=last[x];i;i=e[i].next)
{
int v=e[i].v;
if(!dfs(v)) return false;
}
return true;
}
bool solve()
{
for(int i=2;i<n*2+2;i+=2)
{
if(!mark[i]&&!mark[i^1])
{
c=0;
if(!dfs(i))
{
while(c>0) mark[s[--c]]=false;
if(!dfs(i^1)) return false;
}
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %c %d %c %d %c",&a1,&c1,&a2,&c2,&a3,&c3);
c1=(c1=='R'?0:1);
c2=(c2=='R'?0:1);
c3=(c3=='R'?0:1);
add((2*a1+c1)^1,2*a2+c2);
add((2*a1+c1)^1,2*a3+c3);
add((2*a2+c2)^1,2*a1+c1);
add((2*a2+c2)^1,2*a3+c3);
add((2*a3+c3)^1,2*a2+c2);
add((2*a3+c3)^1,2*a1+c1);
}
if(!solve())
cout<<-1;
else{
for(int i=2;i<2*n+2;i+=2)
{
if(mark[i])
cout<<'R';
else
cout<<'B';
}
}
return 0;
}