• CF776D The Door Problem [2sat]


    考虑 ( exttt{2-SAT})

    首先每个门 (i) 都有一个初始状态 (a_i)

    题目条件每个门只被两个开关控制,那么很显然的 ( exttt{2-SAT})

    (b_{i,{0/1}})记录是第 (1/2) 个开关
    然后就考虑一下门的初始状态 (a_i)

    • 门本身是开的

    你开这个开关为开,另一个也要是开的,
    反之亦然,所以建两对双向边

    • 门本身是关的

    你开这个开关为开,另一个必须是关的
    反之亦然,所以还是建两对双向边

    然后根据 ( exttt{2-SAT}) 的性质,可得答案

    #include<bits/stdc++.h>
    using namespace std ;
    int n , m ;
    const int N = 2e5 + 10 ;
    int a[N] ;
    int b[N][2] ;
    struct Edge { int v , nxt ; } e[N << 2] ;
    int head[N << 1] , cnt = 0 ;
    inline void add(int u , int v) {e[++ cnt] = { v, head[u]} ; head[u] = cnt ; }
    int dfn[N << 1] , low[N << 1] , idx = 0 , st[N << 1], tp = 0 , co[N << 1] , num = 0 ;
    inline void tarjan(int u) { dfn[u] = low[u] = ++ idx ; st[++ tp] = u ;
      for(register int i = head[u] ; i ; i = e[i].nxt) { int v = e[i].v ;
        if(! dfn[v]){ tarjan(v) ; low[u] = min(low[u] , low[v]) ; }
        else if(! co[v]) { low[u] = min(low[v] , dfn[v]) ; }
      } if(low[u] == dfn[u]) { co[u] = ++ num ; while(st[tp] ^ u) co[st[tp --]] = num ; tp -- ; }
    }
    signed main() {
    #ifdef _WIN64
      freopen("0.in"  , "r" , stdin) ;
    #endif
      ios :: sync_with_stdio(false) ; cin.tie(nullptr) ; cout.tie(nullptr) ;
      memset(a , 0 , sizeof(a)) ; memset(b , 0 , sizeof(b)) ;
      cin >> n >> m ;
      for(register int i = 1 ; i <= n ; i ++) { cin >> a[i] ; }
      for(register int i = 1 ; i <= m ; i ++) { int t ; cin >> t ;
        for(register int j = 1 ; j <= t ; j ++) { int x ; cin >> x ; if(b[x][0]) { b[x][1] = i ; } else b[x][0] = i ; }
      }
      for(register int i = 1 ; i <= n ; i ++) {
        if(a[i]) { add(b[i][0] , b[i][1]) ; add(b[i][1] , b[i][0]) ; add(b[i][0] + m , b[i][1] + m) ; add(b[i][1] + m , b[i][0] + m) ; }
        else { add(b[i][0] , b[i][1] + m) ; add(b[i][1] + m , b[i][0]) ; add(b[i][1] , b[i][0] + m) ; add(b[i][0] + m , b[i][1]) ; }
      }
      for(register int i = 1 ; i <= m * 2 ; i ++) { if(! dfn[i]) tarjan(i) ; }
      for(register int i = 1 ; i <= m ; i ++) if(co[i] == co[i + m]) { return cout << "NO
    " , 0 ; }
      cout << "YES
    " ;
      return 0 ;
    }
    
  • 相关阅读:
    Git :版本控制工具进阶
    Git 提交本地代码
    Git创建代码仓库
    Git
    SQLlite数据库的增删改查
    Android学习第十天
    Android学习第九天
    Android学习第八天
    Android学习第七天
    【k8s】Deployment
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12244084.html
Copyright © 2020-2023  润新知