zoukankan      html  css  js  c++  java
  • [NOI2017]游戏【2-SAT(Tarjan+拓扑)+状态压缩二进制枚举】

    题目链接

      有N个场地,每个场地有不适应的赛车,这些场地不能派对应的赛车参赛,又有适合所有赛车的图(不超过8个),并且有的车有怪癖,i图使用col[i]车,则要求j图使用col[j]车。问,是否存在一种方案满足以上条件?并且输出,否则为-1。

      很明显的,对于适合所有赛车的图,我们可以使用二进制枚举它是哪种图——假设它不适合'A'车、'B'车。

      那么,对于剩下的图,我们可以直接进行构造,如果在第i个场地开col[i]车(u),需要让第j个场地开col[j]车(v),我们就让" u -> v ",同理,根据2—SAT的原则,其逆否命题显然成立" v' -> u' "。

      然后,我们先Tarjan缩点来看合法性,再如果合法的话,可以从底向上拓扑来选出一种方案。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <string>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <limits>
      8 #include <vector>
      9 #include <stack>
     10 #include <queue>
     11 #include <set>
     12 #include <map>
     13 #include <bitset>
     14 #include <unordered_map>
     15 #include <unordered_set>
     16 #define lowbit(x) ( x&(-x) )
     17 #define pi 3.141592653589793
     18 #define e 2.718281828459045
     19 #define INF 0x3f3f3f3f
     20 #define HalF (l + r)>>1
     21 #define lsn rt<<1
     22 #define rsn rt<<1|1
     23 #define Lson lsn, l, mid
     24 #define Rson rsn, mid+1, r
     25 #define QL Lson, ql, qr
     26 #define QR Rson, ql, qr
     27 #define myself rt, l, r
     28 #define pii pair<int, int>
     29 #define MP(a, b) make_pair(a, b)
     30 using namespace std;
     31 typedef unsigned long long ull;
     32 typedef unsigned int uit;
     33 typedef long long ll;
     34 const int maxN = 1e5 + 10, maxM = 2e5 + 10;
     35 int N, M, D, dth[10], head[maxN << 1], cnt, id[maxN][3] = {0}, col[maxN][3], all;
     36 struct Eddge
     37 {
     38     int nex, to;
     39     Eddge(int a=-1, int b=0):nex(a), to(b) {}
     40 } edge[maxM << 1];
     41 inline void addEddge(int u, int v)
     42 {
     43     edge[cnt] = Eddge(head[u], v);
     44     head[u] = cnt++;
     45 }
     46 char s[maxN];
     47 inline void init()
     48 {
     49     cnt = 0;
     50     for(int i = 0; i <= all; i ++) head[i] = -1;
     51 }
     52 struct save_edge
     53 {
     54     int u, v;
     55     char s0, s1;
     56     save_edge(int a=0, char _a=0, int b=0, char _b=0):u(a), s0(_a), v(b), s1(_b) {}
     57 } se[maxM];
     58 void build_Graph()
     59 {
     60     init();
     61     char s0, s1;
     62     for(int i = 1, u, v; i <= M; i ++)
     63     {
     64         u = se[i].u; v = se[i].v;
     65         s0 = se[i].s0; s1 = se[i].s1;
     66         if(s0 + 32 == s[u]) continue;
     67         if(s1 + 32 == s[v])
     68         {
     69             if(col[u][0] == s0) addEddge(id[u][0], id[u][1]);
     70             else addEddge(id[u][1], id[u][0]);
     71         }
     72         else
     73         {
     74             int iu = 0, iv = 0;
     75             if(col[u][iu] != s0) iu ++;
     76             if(col[v][iv] != s1) iv ++;
     77             addEddge(id[u][iu], id[v][iv]);
     78             addEddge(id[v][iv ^ 1], id[u][iu ^ 1]);
     79         }
     80     }
     81 }
     82 int dfn[maxN << 1], low[maxN << 1], tot, Stap[maxN << 1], Stop, Belong[maxN << 1], Bcnt;
     83 bool instack[maxN << 1];
     84 void Tarjan(int u)
     85 {
     86     dfn[u] = low[u] = ++tot;
     87     Stap[++Stop] = u;
     88     instack[u] = true;
     89     for(int i = head[u], v; ~i; i = edge[i].nex)
     90     {
     91         v = edge[i].to;
     92         if(!dfn[v])
     93         {
     94             Tarjan(v);
     95             low[u] = min(low[u], low[v]);
     96         }
     97         else if(instack[v]) low[u] = min(low[u], dfn[v]);
     98     }
     99     if(low[u] == dfn[u])
    100     {
    101         int v; Bcnt++;
    102         do
    103         {
    104             v = Stap[Stop --];
    105             instack[v] = false;
    106             Belong[v] = Bcnt;
    107         } while(u ^ v);
    108     }
    109 }
    110 queue<int> Q;
    111 int du[maxN << 1], tp_id[maxN << 1], tp_tot;
    112 vector<int> to[maxN << 1];
    113 void tp_sort()
    114 {
    115     while(!Q.empty()) Q.pop();
    116     for(int i = 1; i <= Bcnt; i ++) if(!du[i]) Q.push(i);
    117     tp_tot = 0;
    118     while(!Q.empty())
    119     {
    120         int u = Q.front(); Q.pop();
    121         tp_id[u] = ++tp_tot;
    122         for(int v : to[u])
    123         {
    124             du[v] --;
    125             if(!du[v]) Q.push(v);
    126         }
    127     }
    128 }
    129 bool Solve()
    130 {
    131     tot = Stop = Bcnt = 0;
    132     for(int i = 1; i <= all; i ++) { dfn[i] = low[i] = 0; instack[i] = false; }
    133     for(int i = 1; i <= all; i ++) if(!dfn[i]) Tarjan(i);
    134     for(int i = 1; i <= N; i ++)
    135     {
    136         if(Belong[id[i][0]] == Belong[id[i][1]]) return false;
    137     }
    138     for(int i = 1; i <= Bcnt; i ++) { to[i].clear(); du[i] = 0; }
    139     for(int u = 1; u <= all; u ++)
    140     {
    141         for(int i = head[u], v; ~i; i = edge[i].nex)
    142         {
    143             v = edge[i].to;
    144             if(Belong[u] == Belong[v]) continue;
    145             to[Belong[v]].push_back(Belong[u]);
    146             du[Belong[u]] ++;
    147         }
    148     }
    149     tp_sort();
    150     for(int i = 1; i <= N; i ++)
    151     {
    152         if(tp_id[Belong[id[i][0]]] < tp_id[Belong[id[i][1]]]) printf("%c", col[i][0]);
    153         else printf("%c", col[i][1]);
    154     }
    155     printf("
    ");
    156     return true;
    157 }
    158 int main()
    159 {
    160     scanf("%d%d", &N, &D);
    161     scanf("%s", s + 1);
    162     all = 0; int kd = 0;
    163     for(int i = 1; i <= N; i ++)
    164     {
    165         id[i][0] = ++all;
    166         id[i][1] = ++all;
    167         switch (s[i])
    168         {
    169             case 'a': { col[i][0] = 'B'; col[i][1] = 'C'; break; }
    170             case 'b': { col[i][0] = 'A'; col[i][1] = 'C'; break; }
    171             case 'c': { col[i][0] = 'A'; col[i][1] = 'B'; break; }
    172             default: { dth[kd ++] = i; break; }
    173         }
    174     }
    175     scanf("%d", &M);
    176     char s0[3], s1[3];
    177     for(int i = 1, u, v; i <= M; i ++)
    178     {
    179         scanf("%d%s%d%s", &u, s0, &v, s1);
    180         se[i] = save_edge(u, s0[0], v, s1[0]);
    181     }
    182     bool ok = false;
    183     for(int Sta = 0; !ok && Sta < (1 << D); Sta ++)
    184     {
    185         for(int i = 0; i < D; i ++)
    186         {
    187             if((Sta >> i) & 1)
    188             {
    189                 s[dth[i]] = 'b';
    190                 col[dth[i]][0] = 'A';
    191                 col[dth[i]][1] = 'C';
    192             }
    193             else
    194             {
    195                 s[dth[i]] = 'a';
    196                 col[dth[i]][0] = 'B';
    197                 col[dth[i]][1] = 'C';
    198             }
    199         }
    200         build_Graph();
    201         ok = Solve();
    202     }
    203     if(!ok) printf("-1
    ");
    204     return 0;
    205 }
    206 /*
    207 4 0
    208 abac
    209 3
    210 1 B 2 A
    211 2 C 3 B
    212 3 B 4 C
    213 */
  • 相关阅读:
    深度神经网络的优化算法
    Python 正则表达式
    《java面试十八式》第一式 --冈本零点零一
    《java面试十八式》--引子
    Redis第二讲【Redis基本命令和五大数据结构】
    redis第一讲【redis的描述,linux和docker下的安装使用】
    springboot中的pom文件是如何管理依赖的
    详谈springboot启动类的@SpringBootApplication注解
    工具类中注入service和dao
    windows下安装ssdb
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/14063414.html
Copyright © 2011-2022 走看看