TV Show Game Gym101987K

TV Show Game
题意: 有k盏灯,n个猜测,每次猜测其中三盏灯的颜色,问使得每次猜测其中至少有两个猜对的方案
思路: 设某次猜测分别是c1,c2,c3。如果c1猜错,那么c2和c3都猜对;如果c2猜错,那么c1和c3都猜对;如果c3猜错,那么c1和c2都猜对.所以根据这样的逻辑建图,然后套模板Tarjan缩点即可

#include
using namespace std;
const int K=5005;
const int N=10005;
int n,k;
vector<int>G[K*2];
void add(int a1,int a2,int b1,int b2)
{
	a1=a1*2+a2,b1=b1*2+b2;
	//cout<<(a1^1)<<' '<<(b1^1)<
	G[a1^1].push_back(b1);
	G[b1^1].push_back(a1);
}
 
int dfn[K*2],dfnIndex,low[K*2],vis[K*2];
int sta[K*2],top;
int bcc[K*2],bccIndex;
void Tarjan(int u){
 
 
    dfn[u] = low[u] = ++dfnIndex;
    vis[u] = true;
    sta[++top] = u;
    for(int i =0; i<G[u].size(); i++){
        int v = G[u][i];
        if(!dfn[v]){
            Tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v]){
            low[u] = min(low[u], dfn[v]);
        }
    }
 
    if(dfn[u] == low[u]){
        ++bccIndex;
        do{
            bcc[sta[top]] = bccIndex;
            vis[sta[top]] = false;
        }while(sta[top--] != u);
    }
}
 
bool check()
{
	for(int i=1;i<=k;i++)
	{
		if(bcc[i<<1]==bcc[(i<<1)|1])
			return false;
	}
	return true;
}
 
int main()
{
	scanf("%d%d",&k,&n);
	for(int i=1;i<=n;i++)
	{
		char c1,c2,c3;
		int  t1,t2,t3;
		int  f1,f2,f3;
		scanf("%d %c %d %c %d %c",&t1,&c1,&t2,&c2,&t3,&c3);
		if(c1=='R')f1=1;else f1=0;
		if(c2=='R')f2=1;else f2=0;
		if(c3=='R')f3=1;else f3=0;
		add(t1,f1,t2,f2);add(t1,f1,t3,f3);
		add(t2,f2,t1,f1);add(t2,f2,t3,f3);
		add(t3,f3,t1,f1);add(t3,f3,t2,f2);
	}
 
	for(int i=2;i<=2*k+1;i++)
	{
		if(!dfn[i])
			Tarjan(i);
	}
	if(check())
	{
		for(int i=1;i<=k;i++)
		{
			if(bcc[i<<1]>bcc[i<<1|1])
				putchar('R');
			else
				putchar('B');
		}
	}
	else
		puts("-1");
	return 0;
}

你可能感兴趣的:(2-SAT)