zoukankan      html  css  js  c++  java
  • Gym 101987K TV Show Game(2-SAT)

    题目链接:https://vj.z180.cn/b4aacc08fc7aab6ce14e7baf13816c24?v=1571542994

    题目要求n个灯(R,B),给出m组赋值方式,每一组中至少有两个是正确的,问是否能找到一组正确的赋值方式.

    2-SAT模板运用强连通分量解决此类真值指派问题.

    对于一组赋值: a x b y c z 来说

    若a假,则bc为真

    若b假,则ac为真

    若c假,则ab为真

    建边跑SCC(强连通分量即可)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn = 1e6 + 5;
    const int inf = 0x3f3f3f3f;
    int dfn[maxn],low[maxn],head[maxn],belong[maxn];
    //dfs序编号,最早能访问到的祖先编号,belong[i]代表i属于哪一个强连通分量
    int num[maxn];//num[i]代表i这个强连通分量中有多少个元素
    stack<int>sta;
    int dfs_clock,cnt,scc_cnt,n,m;//DFS中的编号,边的编号,强连通分量的编号
    struct node
    {
      int v,next;
    }e[maxn];
    void add(int u,int v)
    {
      e[cnt]=(node){v,head[u]};
      head[u]=cnt++;
    }
    void DFS(int u)
    {
      sta.push(u);
      low[u]=dfn[u]=++dfs_clock;
      for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(!dfn[v]){
          DFS(v);
          low[u]=min(low[u],low[v]);
        }
        else if(!belong[v]) low[u]=min(low[u],dfn[v]);
      }
      if(low[u]==dfn[u]){//以u为起点的搜索子树是一个强连通分量
        scc_cnt++;
        for(;;){
          int now=sta.top();
          sta.pop();
          belong[now]=scc_cnt;
          if(now==u)break;
        }
      }
    }
    int two_sat(){
      for(int i = 1;i <= 2 * n;i++){
        if(!dfn[i]){
          DFS(i);
        }
      }
      for(int i = 1;i <= n;i++){
        if(belong[i] == belong[i+n])return 0;
      }
      return 1;
    }
    int x,y,z,xx,yy,zz;
    int main(){
      ios::sync_with_stdio(0);
      cin >> n >> m;
      for(int i = 1;i <= n * 2;i++)head[i] = -1;
      for(int i = 1;i <= m;i++){
        int a,b,c;
        char s1,s2,s3;
        cin >> a >> s1 >> b >> s2 >> c >> s3;
        if(s1 == 'R')x = 1;
        else x = 0;
        if(s2 == 'R')y = 1;
        else y = 0;
        if(s3 == 'R')z = 1;
        else z = 0;
        xx = x ^ 1;
        yy = y ^ 1;
        zz = z ^ 1;
        add(a + xx * n,b + y * n);
        add(a + xx * n,c + z * n);//a错,bc肯定对
        add(b + yy * n,a + x * n);
        add(b + yy * n,c + z * n);//b错,ac肯定对
        add(c + zz * n,a + x * n);
        add(c + zz * n,b + y * n);//c错,ab肯定对
      }
      int x = two_sat();
      if(x){
        for(int i = 1;i <= n;i++){
          if(belong[i] > belong[i+n])cout << 'R';
          else cout << 'B';
        }
        cout << endl;
      }
      else cout << -1 << endl;
      return 0;
    }
  • 相关阅读:
    转载:C# 文件下载(WebClient)
    文档生成业务的商业机会
    Java代码编译和执行的整个过程
    (转)TransitionManager
    安装了phpmyadmin
    转:jQuery框架学习第一天:开始认识jQuery
    转:Http post和 Get的本质区别
    vim基本命令汇总
    jQuery框架学习第二天:jQuery中万能的选择器
    IE的hasLayout属性
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/11724087.html
Copyright © 2011-2022 走看看