• Evanyou Blog 彩带


      题目传送门

    【模板】2-SAT问题

    题目背景

    2-SAT 问题 模板

    题目描述

    有n个布尔变量 $x_1/~x_n$ ,另有$m$个需要满足的条件,每个条件的形式都是“ $x_i$ 为$true/false$或 $x_j$ 为$true/false$”。比如“ $x_1$ 为真或 $x_3$ 为假”、“ $x_7$ 为假或 $x_2$ 为假”。$2-SAT$ 问题的目标是给每个变量赋值使得所有条件得到满足。

    输入输出格式

    输入格式:

     

    第一行两个整数$n$和$m$,意义如体面所述。

    接下来$m$行每行$4$个整数 $i a j b$,表示“ $x_i$ 为$a$或 $x_j$ 为$b$”($a,bin {0,1}$)

     

    输出格式:

     

    如无解,输出“IMPOSSIBLE”(不带引号); 否则输出"POSSIBLE"(不带引号),下 一行n个整数 $x_1$ ~ $x_n$ ( $x_iin {0,1}$),表示构造出的解。

     

    输入输出样例

    输入样例#1: 
    3 1
    1 1 3 0
    输出样例#1: 
    POSSIBLE
    0 0 0

    说明

    1<=n,m<=1e6 , 前3个点卡小错误,后面5个点卡效率,由于数据随机生成,可能会含有( 10 0 10 0)之类的坑


      分析:

      $2-SAT$模板题,特地练下手。

      经典的$2-SAT$模型就不多说了,需要注意的是每次建图时要注意点之间的关系,一旦关系多起来就容易建图建错。(好吧其实是我自己建图建错了两次233333)

      Code:

    //It is made by HolseLee on 21st Aug 2018
    //Luogu.org P4782
    #include<bits/stdc++.h>
    #define Max(a,b) (a)>(b)?(a):(b)
    #define Min(a,b) (a)<(b)?(a):(b)
    using namespace std;
    
    const int N=1e6+7;
    int n,m,bel[N<<1],scc,idx,dfn[N<<1],low[N<<1];
    bool vis[N<<1];
    vector<int>e[N<<1];
    stack<int>sta;
    
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num;
    }
    
    inline void tarjan(int u)
    {
        dfn[u]=low[u]=++idx;
        sta.push(u);vis[u]=true;
        int v;
        for(int i=0;i<e[u].size();++i){
            v=e[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]){
            scc++;
            do{
                v=sta.top();sta.pop();
                vis[v]=false;bel[v]=scc;
            }while(v!=u);
        }
    }
    
    int main()
    {
        n=read();m=read();
        int a,b,x,y;
        for(int i=1;i<=m;++i){
            a=read(),x=read(),b=read(),y=read();
            e[a+(x^1)*n].push_back(b+y*n);
            e[b+(y^1)*n].push_back(a+x*n);
        }
        for(int i=1;i<=(n<<1);++i)
        if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;++i)
        if(bel[i]==bel[i+n]){
            printf("IMPOSSIBLE
    ");
            return 0;
        }
        printf("POSSIBLE
    ");
        for(int i=1;i<=n;++i){
            printf("%d ",(bel[i]>bel[i+n]));
        }
        return 0;
    }
  • 相关阅读:
    计算机网络知识总结-网络安全
    域名恶意指向的解决方法
    域名恶意解析的原因是什么
    域名被人恶意解析的解决方法
    防止域名被恶意解析
    公安部网防G01-网站安全卫士软件/linux防御
    详解web容器
    关于 服务器ip和域名进行一个绑定
    重新温习软件设计之路(2)
    重新温习软件设计之路(1)
  • 原文地址:https://www.cnblogs.com/cytus/p/9509774.html
Copyright © 2020-2023  润新知