zoukankan      html  css  js  c++  java
  • Codeforces Round #400 D. The Door Problem(2-sat)

    题目链接:Codeforces Round #400 D. The Door Problem

    题意:

    有n扇门,每扇门有个初始状态,并且受两个开关控制。

    现在给你m个开关控制门的信息,每个开关能将它所控制的门的状态翻转。

    问能不能通过一定操作,将所以的门的状态都处于开的情况。

    题解:

    这题用2sat,也可以用并查集判断联通块。这里我用2sat。

    因为一个开关可以控制多扇门,而每个门只由两个开关控制,所以这里我们考虑对这m个开关建图。

    如果这扇门的状态为1,那么要让它保持1的状态,我们只能同时按下控制它的两个开关或者两个都不按。

    如果这扇门的状态为0,那么我们必须按并且只能按其中一个控制这扇门的开关。

    然后根据这个建图。

     1 #include<bits/stdc++.h>
     2 #define mst(a,b) memset(a,b,sizeof(a))
     3 #define F(i,a,b) for(int i=a;i<=b;++i)
     4 using namespace std;
     5 const int N=1e5+7;
     6 namespace Twosat
     7 {
     8     int q[N*4],t,n,g[N*2],v[N*4],nxt[N*4],ed;bool vis[N*2];
     9     void init(int _n){n=_n,mst(g,0),mst(vis,0),ed=0;}
    10     void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
    11     bool dfs(int x){
    12         if(vis[x>n?x-n:x+n])return 0;
    13         if(vis[x])return 1;
    14         vis[q[++t]=x]=1;
    15         for(int i=g[x];i;i=nxt[i])if(!dfs(v[i]))return 0;
    16         return 1;
    17     }
    18     bool solve(){
    19         F(i,1,n)if(!vis[i]&&!vis[i+n]){
    20             t=0;
    21             if(!dfs(i)){
    22                 while(t)vis[q[t--]]=0;
    23                 if(!dfs(i+n))return 0;
    24             }
    25         }
    26         return 1;
    27     }
    28 }
    29 int n,m,a[N],t,u,v,x;
    30 
    31 vector<int>q[N];
    32 
    33 int main(){
    34     scanf("%d%d",&n,&m);
    35     Twosat::init(m);
    36     F(i,1,n)scanf("%d",a+i);
    37     F(i,1,m)
    38     {
    39         scanf("%d",&t);
    40         while(t--)
    41         {
    42             scanf("%d",&x);
    43             q[x].push_back(i);
    44         }
    45     }
    46     F(i,1,n)
    47     {
    48         int u=q[i][0],v=q[i][1];
    49         if(a[i])
    50         {
    51             Twosat::adg(u+m,v+m),Twosat::adg(v+m,u+m);
    52             Twosat::adg(u,v),Twosat::adg(v,u);
    53         }
    54         else {
    55             Twosat::adg(u+m,v),Twosat::adg(v,u+m);
    56             Twosat::adg(u,v+m),Twosat::adg(v+m,u);
    57         }
    58     }
    59     Twosat::solve()?puts("YES"):puts("NO");   
    60     return 0; 
    61 }
    View Code
  • 相关阅读:
    Java面向对象类与对象整理
    Java案例整理
    Java引用类型传递整理
    Java基础方法整理
    Java流程控制语句和数组整理
    Java流程语句
    Java运算符和引用数据类型(Scanner、Random)
    Java概念、语法和变量基础整理
    Mysql连接查询、子查询、联合查询 整理
    Mysql数据约束 整理
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6442063.html
Copyright © 2011-2022 走看看