• 模板:2-SAT


    2-SAT算法

    实际上是每个变量有两个状态把

    然后扩展开来

    注意每个数组开原来的二倍

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn=1000010;
     7 int head[maxn<<1], cnt;
     8 int dfn[maxn<<1], low[maxn<<1], st[maxn<<1];
     9 int scc[maxn<<1];//强连通分量的拓扑序
    10 bool in[maxn<<1];
    11 int m, n, top, num, ct;
    12 struct edge{
    13     int to, next;
    14 }a[maxn<<2];
    15 void add(int from, int to){
    16     cnt++;
    17     a[cnt].to=to;
    18     a[cnt].next=head[from];
    19     head[from]=cnt;
    20 }
    21 void tarjan(int u){//缩点
    22     low[u]=dfn[u]=++num;
    23     st[top++]=u;
    24     in[u]=true;
    25     for(int i=head[u]; i; i=a[i].next){
    26         int v=a[i].to;
    27         if(!dfn[v]){
    28             tarjan(v);
    29             low[u]=min(low[u],low[v]);
    30         }
    31         else if(in[v]) low[u]=min(low[u],dfn[v]);
    32     }
    33     if(low[u]==dfn[u]){
    34         int v;
    35         ct++;
    36         do{
    37             v=st[--top];
    38             in[v]=false;
    39             scc[v]=ct;
    40         }while(u!=v);
    41     }
    42 }
    43 bool sat(){
    44     for(int i=1; i<=n*2; i++){
    45         if(!dfn[i]) tarjan(i);
    46     }
    47     for(int i=1; i<=n; i++){
    48         if(scc[i]==scc[i+n]) return false;//如果两个在同一个,也就意味着自相矛盾不存在
    49     }
    50     return true;
    51 }
    52 int main(){
    53     scanf("%d%d",&n,&m);
    54     for(int i=1; i<=m; i++){
    55         int a, b, av, bv;
    56         scanf("%d%d%d%d",&a,&av,&b,&bv);
    57         int na=av^1, nb=bv^1;//a表示条件a选0的情况,a+n表示条件a选1的情况。 
    58         add(a+na*n, b+bv*n);//相应建图方式,具体不理解可以手动推一下
    59         add(b+nb*n, a+av*n);
    60     }
    61     if(sat()){
    62         printf("POSSIBLE
    ");
    63         for(int i=1; i<=n; i++)
    64             printf("%d ",scc[i]>scc[i+n]);//反着的拓扑序,如果大于成立则说明1其实是拓扑序大的,小于成立反之
    65     }
    66     else printf("IMPOSSIBLE");
    67     return 0;
    68 }

    注意每个数组开

  • 相关阅读:
    Vue之仿百度搜索框
    Vue之交互
    Vue之键盘事件
    Vue之事件冒泡
    Vue之阻止默认行为
    sql注入常用注释符总结
    什么是Git
    Github部署博客
    php笔记
    JavaScript(更新中)
  • 原文地址:https://www.cnblogs.com/Aze-qwq/p/9910270.html
Copyright © 2020-2023  润新知