• Codeforces 776D【The Door Problem】(2-SAT)


    难度CF2000分

    题意:给你n个门,m把锁。每个门由2把锁控制,给你每个门的初始状态以及每把锁可以控制的t个门,问你能否使用锁将这些门全部打开。0是关闭,1是开启。

    题解:因为很久没使用2-sat导致自己一开始不会做这个题,然后看了题解才恍然大悟。我们这么来想:因为每个门只能被2把钥匙控制,如果门初始的状态是0,那么也就是控制该门的2个钥匙只有1个钥匙生效;如果门的状态是1,那么就是控制该门的2个钥匙都生效或者都不生效。那么我们就可以将其转化为2-sat模型。生效为2*i,不生效为2*i+1。然后进行建边操作,最后跑tarjan看是否有id[2*i]==id[2*i+1]的情况,如果有的话说明不行,输出NO,反之输出YES

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=2e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int dfn[maxn],low[maxn],id[maxn],vis[maxn],cnt,tott;
    stack<int> s;
    void tarjan(int x){
        dfn[x]=low[x]=++tott;
        s.push(x);vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(low[x]==dfn[x]){
            ++cnt;
            while(1){
                int now=s.top();s.pop();
                id[now]=cnt;
                vis[now]=0;
                if(x==now) break;
            }
        }
    }
    int n,m,a[maxn];
    vector<int> w[maxn];
    int main(){
        scanf("%d%d",&n,&m);mem(head,-1);
        rep(i,1,n) scanf("%d",&a[i]);
        rep(i,1,m){
            int t;scanf("%d",&t);
            while(t--){
                int x;scanf("%d",&x);
                w[x].push_back(i);
            }
        }
        rep(i,1,n){
            int x=w[i][0],y=w[i][1];
            x*=2;y*=2;
            if(a[i]==0){
                add(x,y+1);add(y+1,x);
                add(x+1,y);add(y,x+1);
            }else{
                add(x,y);add(y,x);
                add(x+1,y+1);add(y+1,x+1);
            }
        }
        rep(i,2,2*m+1){
            if(!dfn[i]) tarjan(i);
        }
        for(int i=1;i<=m;i++){
            if(id[i*2]==id[i*2+1]){
                puts("NO");return 0;
            }
        }
        puts("YES");
    }
    View Code
  • 相关阅读:
    大数据概述
    c语言文法
    实验一 词法分析程序实验
    语法分析程序
    第一篇博客~关于编译原理的理解
    《DenseNet Models for Tiny ImageNet Classification》课程设计论文
    物体检测的尺度效应实验
    16路PWM输出的pca9685模块
    Rocketlab公司火箭Electron介绍
    网址图书收藏
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13863942.html
Copyright © 2020-2023  润新知