Gym 101987K TV Show Game(2-SAT)

题解:

转化为命题的形式就是,如果这个位置猜错了那么其他两个位置就必须要猜对。

#include 
using namespace std;
//#define int long long
const int N=2e6+10;
stack<int> st;
int head[N],e[N],ne[N],dfn[N],low[N],ins[N],cnt,id[N],ts,scc;
void add(int a,int b){
     
    e[cnt]=b,ne[cnt]=head[a],head[a]=cnt++;
}
void tarjan(int u)
{
     
    dfn[u]=low[u]=++ts;
    st.push(u); ins[u]=1;
    for(int i=head[u];~i;i=ne[i]){
     
        int j=e[i];
        if(!dfn[j]){
     
            tarjan(j);
            low[u]=min(low[u],low[j]);
        }else if(ins[j]) low[u]=min(low[u],dfn[j]);
    }
    if(low[u]==dfn[u]){
     
        int y;
        scc++;
        do{
     
            y=st.top(); st.pop(); ins[y]=0;
            id[y]=scc;
        }while(y!=u);
    }
}
void solve(){
     
    memset(head,-1,sizeof head);
    int n,k; scanf("%d%d",&k,&n);
    for(int i=1;i<=n;i++){
     
        string a,b,c;
        int posa,posb,posc;
        cin>>posa>>a>>posb>>b>>posc>>c;
        int x,xx,y,yy,z,zz;
        x=a=="R";y=b=="R";z=c=="R";
        xx=x^1; yy=y^1; zz=z^1;
        add(posa+xx*k,posb+y*k);
        add(posb+yy*k,posa+x*k);
        add(posa+xx*k,posc+z*k);
        add(posc+zz*k,posa+x*k);
        add(posb+yy*k,posc+z*k);
        add(posc+zz*k,posb+y*k);
    }
    for(int i=1;i<=2*k;i++) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=k;i++){
     
        if(id[i]==id[i+k]){
     
            puts("-1");
            return;
        }
    }
    for(int i=1;i<=k;i++){
     
        if(id[i]<id[i+k]) printf("B");
        else printf("R");
    }
    puts("");
}
signed main(){
     
    solve();
#ifndef ONLINE_JUDGE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

你可能感兴趣的:(图论)