zoukankan      html  css  js  c++  java
  • CF776D The Door Problem[2-SAT]

    翻译

    对于一扇门,如果是关的,那么他必须使用其中一个开关开开来,如果是开的,要么使用两个开关,要么啥都不做。这样,每扇门恰好对应两种状态,要选一个。

    考虑用2-SAT模型解决。连边的话是对于一个机关,所有他控制的门都应该一起选(具体地说,对于一扇关闭的门,这个机关是他的第几个机关,就是哪个状态,如果是开着的,必须对应使用开关两次的状态),所以这些状态点互相连双向边。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define mst(x) memset(x,0,sizeof x)
    #define dbg(x) cerr << #x << " = " << x <<endl
    #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair<int,int> pii;
    template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    template<typename T>inline T read(T&x){
        x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
        while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    }
    const int N=2e5+7;
    struct thxorz{
        int head[N],to[N<<2],nxt[N<<2],tot;
        inline void link(int x,int y){
            to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
            to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
        }
    }G;
    int n,m;
    int sta[N],vis[N],lock[N];
    #define y G.to[j]
    int dfn[N],low[N],stk[N],instk[N],Top,tim,scc,bel[N];
    void tarjan(int x){
        dfn[x]=low[x]=++tim,stk[++Top]=x,instk[x]=1;
        for(register int j=G.head[x];j;j=G.nxt[j]){
            if(!dfn[y])tarjan(y),MIN(low[x],low[y]);
            else if(instk[y])MIN(low[x],dfn[y]);
        }
        if(dfn[x]==low[x]){
            int tmp;++scc;//dbg(scc);
            do instk[tmp=stk[Top--]]=0,bel[tmp]=scc;while(tmp^x);
        }
    }
    #undef y
    int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
        read(n),read(m);
        for(register int i=1;i<=n;++i)read(sta[i]);
        for(register int i=1,k;i<=m;++i){
            read(k);
            for(register int j=1,x,las=0;j<=k;++j,las=x){
                lock[j]=read(x);
                if(las){
                    if(sta[x])sta[las]?(G.link(x,las),G.link(x+n,las+n)):(G.link(x,las+vis[las]*n),G.link(x+n,las+(1-vis[las])*n));
                    else sta[las]?(G.link(x+vis[x]*n,las),G.link(x+(1-vis[x])*n,las+n)):(G.link(x+vis[x]*n,las+vis[las]*n),G.link(x+(1-vis[x])*n,las+(1-vis[las])*n));
                }
            }
            for(register int j=1;j<=k;++j)++vis[lock[j]];
        }
        for(register int i=1;i<=n<<1;++i)if(!dfn[i])tarjan(i);
        for(register int i=1;i<=n;++i)if(bel[i]==bel[i+n]){puts("NO");return 0;}
        puts("YES");return 0;
    }
    View Code

    注意要连反向边。。我忘连了所以挂了一次。。

    总结:主要在于转化模型。。看到2数字要敏感。。把每种个体转化为对应的01状态。。

  • 相关阅读:
    【转】awk用法介绍
    【转】Shell执行MySql操作
    curl访问nagios中Host Status Details For All Host Groups页面的方法
    【转】命令行浏览器 curl 命令详解,Linux中访问url地址
    【转】DELL R710服务器可以安装的VMWare ESX Server 4.1 全套下载带注册码
    【转】一些常用的Vi命令,可帮助脱离鼠标
    乐观处世,诚实做人,不骄不躁,积极进取; 勇于创新,踏实实现,谨慎规划,付诸实践; 事在人为
    【转】Linux方向职业分析
    【转】[Asp.net]常见数据导入Excel,Excel数据导入数据库解决方案,总有一款适合你!
    【转】Nagios安装部署与Cacti整合文档超精细版本
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11730882.html
Copyright © 2011-2022 走看看