[NOI2017]遊戲

嘟嘟嘟


這題也太暴力了……


考慮若是沒有'x'的狀況,那就是2-SAT水題。有了'x'怎麼辦?由於'x'最多隻有8個,因此咱們暴力枚舉,時間複雜度\(O((n + m) * 3 ^ 8)\)。這算出來後大約是\(9e8\),因此就沒敢寫……


然而這實際上根本跑不滿,找到合法的就exit(0),幾乎每個點不到200ms就跑出來了……


不過有一個地方仍是要講一下的,就是若是賽道\(i\)選了\(h_i\)車,則\(j\)就得選\(h_j\)。首先若是\(h_i\)不存在,不連邊;若是\(h_j\)不存在。連邊\(i -> i'\),表示選了\(i\)就gg;不然要連兩條邊,分別是\(i->j\)\(j' ->i'\),剛開始我以爲第二條不用連,畢竟選\(h_j\)不選\(h_i\)是能夠的。但咱們得考慮2-SAT的對稱性,即若是\(j\)不選\(h_j\),則\(i\)只能選除\(h_i\)以外的另外一輛。ios

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 5e4 + 5;
const int maxe = 4e5 + 5;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
  freopen("game.in", "r", stdin);
  freopen("game.out", "w", stdout);
#endif
}

char s[maxn], c1[2], c2[2], asc[maxn << 1];
int n, d, m;
struct Node
{
  int x; char c1; int y; char c2;
}q[maxn << 1];

int h[maxn][3], a[maxn], cnt = 0;
In void init()
{
  for(int i = 1; i <= n; ++i)
    {
      if(s[i] == 'x') a[++cnt] = i;
      else if(s[i] == 'a') h[i][1] = i, h[i][2] = n + i, asc[i] = 'B', asc[i + n] = 'C';
      else if(s[i] == 'b') h[i][0] = i, h[i][2] = n + i, asc[i] = 'A', asc[i + n] = 'C';
      else if(s[i] == 'c') h[i][0] = i, h[i][1] = n + i, asc[i] = 'A', asc[i + n] = 'B';
    }
}

struct Edge
{
  int nxt, to;
}e[maxe];
int head[maxn << 1], ecnt = -1;
In void addEdge(int x, int y)
{
  e[++ecnt] = (Edge){head[x], y};
  head[x] = ecnt;
}

bool in[maxn << 1];
int st[maxn << 1], top = 0;
int dfn[maxn << 1], low[maxn << 1], dcnt = 0;
int col[maxn << 1], ccol = 0;
In void tarjan(int now)
{
  st[++top] = now; in[now] = 1;
  dfn[now] = low[now] = ++dcnt;
  for(int i = head[now], v; ~i; i = e[i].nxt)
    {
      if(!dfn[v = e[i].to])
    {
      tarjan(v);
      low[now] = min(low[now], low[v]);
    }
      else if(in[v]) low[now] = min(low[now], dfn[v]);
    }
  if(low[now] == dfn[now])
    {
      int x; ++ccol;
      do
    {
      x = st[top--]; in[x] = 0;
      col[x] = ccol;
    }while(x ^ now);
    }
}
In void build()
{
  for(int i = 1; i <= m; ++i)
    {
      int u = h[q[i].x][q[i].c1 - 'A'], v = h[q[i].y][q[i].c2 - 'A'];
      if(!u) continue;
      if(!v) addEdge(u, u > n ? u - n : u + n);
      else addEdge(u, v), addEdge(v > n ? v - n : v + n, u > n ? u - n : u + n);
    }
}
In void clear()
{
  ecnt = -1; top = dcnt = ccol = 0;
  Mem(head, -1), Mem(dfn, 0), Mem(low, 0), Mem(in, 0);
}

In bool check()
{
  clear(), build();
  for(int i = 1; i <= (n << 1); ++i) if(!dfn[i]) tarjan(i);
  for(int i = 1; i <= n; ++i)
    if(col[i] == col[i + n]) return 0;
  return 1;
}
In void print()
{
  for(int i = 1; i <= n; ++i)
    putchar(col[i] < col[i + n] ? asc[i] : asc[i + n]);
  enter;
}
In void dfs_bf(int now)
{
  if(now == cnt + 1)
    {
      if(check()) print(), exit(0);
      return;
    }
  for(int i = 0; i < 3; ++i)
    {
      h[a[now]][(i + 2) % 3] = a[now], asc[a[now]] = 'A' + (i + 2) % 3;
      h[a[now]][(i + 1) % 3] = a[now] + n, asc[a[now] + n] = 'A' + (i + 1) % 3;
      h[a[now]][i] = 0;
      dfs_bf(now + 1);
    }
}

int main()
{
  MYFILE();
  Mem(head, -1);
  n = read(), d = read(); scanf("%s", s + 1);
  m = read();
  for(int i = 1; i <= m; ++i)
    {
      int x = read(); scanf("%s", c1); int y = read(); scanf("%s", c2);
      q[i] = (Node){x, c1[0], y, c2[0]};
    }
  init();
  dfs_bf(1);
  puts("-1");
  return 0;
}
相關文章
相關標籤/搜索