2018-2019 ACM-ICPC, Asia Seoul Regional Contest ( TV Show Game )2-SAT

花了几天时间肝了几道2-SAT的题。

越做题越会发现,这个东西挺模板的了解原理之后只要会建边基本上就做出来了(除非加什么花里胡哨的二分)。

这篇博客写一个Seoul区域赛场的一个2-SAT问题。

读者可以去codeforces.com的gym搜seoul然后倒数第二题就是这道题了。

首先我们捋一下2-SAT解决问题流程:

其实2-SAT细究的话,也就是个  Tarjan求强连通分量+缩点反向建边+拓扑排序+染色

1.  根据约束条件建边

2.  tarjan求出强连通分量,并且对于同一个强连通分量中的点编同一个号。

3.  判断是否有同一个集合中的两个点出现在同一个强连通分量中,如果有那么无解,如果没,那么就一定存在解。

4.  缩点,把一个强连通分量视为一个点,根据我们步骤2中对强连通分量编的号缩点。

5.  对于缩点之后,我们将边反向,建立新图。

6.  拓扑排序,如果未染色就对新图结点染色。

7.  输出结果,对于所有集合,同一输出颜色相同的点。

当我们做过几个题后,如果不是花里胡哨的题目的话我们可以很容易的发现,建边是整个题的灵魂,建好边就成功了百分之80。然后改输出就完成了百分之90。模板别抄错就AC了

接下来我们来说一些建边的技巧:

1.   如果选 A 必须 不选 B, 那么建立  A - > !B   ,和   B --> !A 的两条边

2.   如果选  A 必须选   B,那么建立  A  -->B 的 ,和   !B -->!A的两个边

3.   无论如何必须选A   ,建立  !A  --- >  A  的边(方向千万不要弄反)

说白了,   ----->   这个箭头的意思就是离散数学中的 “蕴含”,就是选了左边的就一定要选右边的。

接下来说题目大意  : 

      这里有N鸽灯泡,每种灯泡可能有两种颜色,R是红色,B是绿色。

      然后有m位老鸽来猜灯泡的颜色,规定一个人只能描述三个灯泡的颜色,而且至少说对两个灯泡。

     问你有无可行解满足题意。

      可以对n鸽灯泡的两种状态作为2-SAT问题中的一个集合中的两个元素。那么比如说1号灯泡(为了建图编号方便,我们对这个一号灯泡编号减一,下边就说0号灯泡了)  ,我们对他有两个结点,2* i 表示他是红色,2*i+1表示蓝色。

    接下来我们建边,对于每一位老鸽,他说的至少有两个对的,我们来找隐含的而约束条件如果他猜 1R 2B 3B,是不是意思就是如果第一个灯泡是蓝色,那么其他两个他说的一定是对的,也就是说 “1号灯泡蓝色  ---> 2号灯泡蓝色,3号灯泡蓝色”  ,对于他猜的二号灯泡同理建边,所以对于一位老鸽来说,要建立6跳边,然后抄模板,输出,AC。

代码(我这里建边比较辣鸡,写的有点长,读者完全可以按小编是弱智处理):

#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stdio.h>
#include<cmath>
#include<string>
#include<queue>
#include<stack>
#include<queue>
#define ll long long
using namespace std;
const ll MAXN=1e4+5;
const ll MAXM=6e6+5;
int n,m,dfn[MAXN],tot,low[MAXN],belong[MAXN],head[MAXN];
int cnt,col,tot2;
int cnt2,head2[MAXN],in[MAXN],color[MAXN],cp[MAXN];
bool Instack[MAXN];
struct edge
{
    int from,to,next;
}Edge[MAXM],Edge2[MAXM];
struct Time
{
    int val;
    int x,y;
}C[MAXN];
stack<int>S;
void add(int x,int y)
{
    Edge[++tot].to=y;Edge[tot].from=x;
    Edge[tot].next=head[x];head[x]=tot;
}
void add2(int x,int y)
{
    Edge2[++tot2].to=y;Edge2[tot2].from=x;
    Edge2[tot2].next=head2[x];head2[x]=tot2;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++cnt;
    S.push(x);
    Instack[x]=1;
    for(int i=head[x];i!=-1;i=Edge[i].next){
        int to=Edge[i].to;
        if(!dfn[to]){
            tarjan(to);
            low[x]=min(low[to],low[x]);
        }
        else if(Instack[to]){
            low[x]=min(low[x],dfn[to]);
        }
    }
    if(dfn[x]==low[x]){
        Instack[x]=0;
        belong[x]=++col;
        while(S.top()!=x){
            belong[S.top()]=col;
            Instack[S.top()]=0;
            S.pop();
        }
        S.pop();
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    memset(head2,-1,sizeof(head2));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        int a,b,c;

        char cc,d,e;
        cin>>a>>cc>>b>>d>>c>>e;a--,b--,c--;
        if(cc=='R'){
            if(d=='R'){
                add(2*a+1,2*b);
            }
            else if(d=='B'){
                add(2*a+1,2*b+1);
            }
            if(e=='R'){
                add(2*a+1,2*c);
            }
            else if(e=='B'){
                add(2*a+1,2*c+1);
            }
        }
        else {
            if(d=='R'){
                add(2*a,2*b);
            }
            else if(d=='B'){
                add(2*a,2*b+1);
            }
            if(e=='R'){
                add(2*a,2*c);
            }
            else if(e=='B'){
                add(2*a,2*c+1);
            }
        }

        if(d=='R'){
            if(cc=='R'){
                add(2*b+1,2*a);
            }
            else if(cc=='B'){
                add(2*b+1,2*a+1);
            }
            if(e=='R'){
                add(2*b+1,2*c);
            }
            else if(e=='B'){
                add(2*b+1,2*c+1);
            }
        }
        else {
            if(cc=='R'){
                add(2*b,2*a);
            }
            else if(cc=='B'){
                add(2*b,2*a+1);
            }
            if(e=='R'){
                add(2*b,2*c);
            }
            else if(e=='B'){
                add(2*b,2*c+1);
            }
        }

        if(e=='R'){
            if(cc=='R'){
                add(2*c+1,2*a);
            }
            else if(cc=='B'){
                add(2*c+1,2*a+1);
            }
            if(d=='R'){
                add(2*c+1,2*b);
            }
            else if(d=='B'){
                add(2*c+1,2*b+1);
            }
        }
        else {
            if(cc=='R'){
                add(2*c,2*a);
            }
            else if(cc=='B'){
                add(2*c,2*a+1);
            }
            if(d=='R'){
                add(2*c,2*b);
            }
            else if(d=='B'){
                add(2*c,2*b+1);
            }
        }
    }
    while(S.size())S.pop();
    for(int i=0;i<2*n;i++){
        if(!dfn[i])tarjan(i);
        //if(!dfn[2*i+1])tarjan(i*2+1);
    }

    bool flag=1;
    for(int i=0;i<n;i++){//
        if(belong[2*i]==belong[2*i+1]){
            flag=0;break;
        }
        else{
            cp[belong[2*i]]=belong[2*i+1];
            cp[belong[2*i+1]]=belong[2*i];
        }
    }
    memset(head2,-1,sizeof(head2));
    for(int i=1;i<=tot;i++){//
        if(belong[Edge[i].from]!=belong[Edge[i].to]){
            add2(belong[Edge[i].to],belong[Edge[i].from]);
            in[belong[Edge[i].from]]++;
        }
    }
    queue<int>Q;
    while(!Q.empty())Q.pop();
    for(int i=1;i<=col;i++){//
        if(in[i]==0)Q.push(i);
    }
    while(!Q.empty())
    {
        int tmp=Q.front();Q.pop();
        if(color[tmp]==0){
            color[tmp]=1;
            color[cp[tmp]]=2;
        }
        for(int i=head2[tmp];i!=-1;i=Edge2[i].next){
            int to=Edge2[i].to;//cout<<" * "<<to<<endl;
            if(--in[to]==0)Q.push(to);
        }
    }
    if (flag){
       // printf("YES\n");
        for(int i = 0; i < n; i++)
        {
            if(color[belong[2*i]] == 1)
            printf("R");
            else
            printf("B");
        }
        printf("\n");
    }
    else printf("-1\n");

}
/*
5 6
1 B 3 R 4 B
2 B 3 R 4 R
1 B 2 R 3 R
3 R 4 B 5 B
3 B 4 B 5 B
1 R 2 R 4 R




*/

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/89403132