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
  • 相关阅读:
    作业 20181204-1 每周例行报告
    对团队成员公开感谢
    附加作业 软件工程原则的应用实例分析
    作业 20181127-2 每周例行报告
    作业 20181120-1 每周例行报告
    作业 20181113-2 每周例行报告
    作业 20181030-4 每周例行报告
    作业 20181023-3 每周例行报告
    SDWebImage的实现原理与底层结构拆解
    计算文件或者文件夹的大小用于计算下载速度或者是显示清除缓存大小
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6442063.html
Copyright © 2011-2022 走看看