Description

题库链接

小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏。

小 L 的赛车有三辆,分别用大写字母 A、B、C 表示。地图一共有四种,分别用小写字母 x、a、b、c 表示。其中,赛车 A 不适合在地图 a 上使用,赛车 B 不适合在地图 b 上使用,赛车 C 不适合在地图 c 上使用,而地图 x 则适合所有赛车参加。适合所有赛车参加的地图并不多见,最多只会有 d 张。

\(n\) 场游戏的地图可以用一个小写字母组成的字符串描述。例如: S=xaabxcbc 表示小 L 计划进行 \(8\) 场游戏,其中第 \(1\) 场和第 \(5\) 场的地图类型是 x ,适合所有赛车,第 \(2\) 场和第 \(3\) 场的地图是 a ,不适合赛车 A ,第 \(4\) 场和第 \(7\) 场的地图是 b ,不适合赛车 B ,第 \(6\) 场和第 \(8\) 场的地图是 c ,不适合赛车 C 。

小 L 对游戏有一些特殊的要求,这些要求可以用四元组 \((i, h_i, j, h_j)\) 来描述,表示若在第 \(i\) 场使用型号为 \(h_i\) 的车子,则第 \(j\) 场游戏要使用型号为 \(h_j\) 的车子。

你能帮小 L 选择每场游戏使用的赛车吗?如果有多种方案,输出任意一种方案。如果无解,输出 -1(不含双引号)。

\(1\leq n\leq 50000,d\leq 8,1\leq m\leq 100000\)

Solution

容易发现,对于除 x 以外的位置,只能选择两个中的一个,可以建立 \(\text{2-SAT}\) 模型。剩下的 x 的位置,因为数量少,可以枚举。不过只要枚举这一位置是 a 或是 b ,因为 c 的情况已经被前两种情况涵盖了。

对于边的建立,对于四元组 \((i, h_i, j, h_j)\) ,记第 \(i\) 个位置上的字符为 \(S_i\) 。

  • 若 \(h_i=S_i\) ,直接忽略;
  • 若 \(h_j=S_j\) ,建一条 \(i\rightarrow i'\) 的边,表示强制选择 \(S_i\) 对应的另一种字符;
  • 其余情况,建边 \(i\rightarrow j\) , \(j'\rightarrow i'\)

直接跑 \(\text{2-SAT}\) 即可,复杂度是 \(O\left(2^d\times(m+n)\right)\) 。

Code

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = (50000+5)<<1, M = 100000+5; int n, d, m, lst[10], tot, a[M], b[M], h1[M], h2[M];
char ch[N], s[2];
struct tt {int to, next; } edge[M<<1];
int path[N], top;
vector<int> scc[N], to[N];
vector<int>::iterator it;
queue<int> Q;
int dfn[N], low[N], ins[N], id[N], in[N], num, times, S[N], tp, cs[N]; void add(int u, int v) {edge[++top] = (tt){v, path[u]}, path[u] = top; }
int idx(int i, int c) {
if (ch[i] != 'c') return i+n*(c == 'C');
return i+n*(c == 'B');
}
int inv(int x) {return x <= n ? x+n : x-n; }
void tarjan(int u) {
dfn[u] = low[u] = ++times; ins[u] = 1; S[++tp] = u;
for (int i = path[u], v; i; i = edge[i].next) {
v = edge[i].to;
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (ins[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
++num; int v = 0;
do {
v = S[tp--]; id[v] = num;
scc[num].pb(v); ins[v] = 0;
}while (v != u);
}
}
void solve() {
memset(path, top = 0, sizeof(path));
for (int i = 1; i <= m; i++) {
if (ch[a[i]] == h1[i]+32) continue;
else if (ch[b[i]] == h2[i]+32) add(idx(a[i], h1[i]), inv(idx(a[i], h1[i])));
else {
int x = idx(a[i], h1[i]), y = idx(b[i], h2[i]);
add(x, y), add(inv(y), inv(x));
}
}
for (int i = 1; i <= n*2; i++) scc[i].clear(); num = 0;
memset(dfn, times = 0, sizeof(dfn));
for (int i = 1; i <= n*2; i++) if (!dfn[i]) tarjan(i);
for (int i = 1; i <= n; i++) if (id[i] == id[i+n]) return;
for (int u = 1; u <= n*2; u++)
for (int i = path[u], v; i; i = edge[i].next)
if (id[u] != id[v = edge[i].to]) to[id[v]].pb(id[u]), ++in[id[u]];
for (int i = 1; i <= num; i++) if (in[i] == 0) Q.push(i);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
if (ins[u]) continue; cs[u] = 1;
for (it = scc[u].begin(); it != scc[u].end(); it++) ins[id[inv(*it)]] = 1;
for (it = to[u].begin(); it != to[u].end(); it++) if (!(--in[*it])) Q.push(*it);
}
for (int i = 1; i <= n; i++)
if (cs[id[i]]) putchar('A'+(ch[i] == 'a'));
else putchar('C'-(ch[i] == 'c'));
exit(0);
}
void dfs(int x) {
if (x > tot) {solve(); return; }
ch[lst[x]] = 'a'; dfs(x+1);
ch[lst[x]] = 'b'; dfs(x+1);
}
void work() {
scanf("%d%d%s", &n, &d, ch+1);
for (int i = 1; i <= n; i++) if (ch[i] == 'x') lst[++tot] = i;
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
scanf("%d%s", &a[i], s); h1[i] = s[0];
scanf("%d%s", &b[i], s); h2[i] = s[0];
}
dfs(1); puts("-1");
}
int main() {work(); return 0; }

[NOI 2017]游戏的更多相关文章

  1. NOI 2017滚粗退役记

    NOI 2017 游记 又到了OIer退役了的季节 Day -1 今天是报到日. 中午11点多的动车.动车上和dick32165401和runzhe2000谈笑风生.顺便用dick32165401的流 ...

  2. CTSC 2017 游戏[概率dp 线段树]

    小 R 和室友小 B 在寝室里玩游戏.他们一共玩了 $n$ 局游戏,每局游戏的结果要么是小 R 获胜,要么是小 B 获胜. 第 $1$ 局游戏小 R 获胜的概率是 $p_1$,小 B 获胜的概率是 $ ...

  3. NOI Online 游戏 树形dp 广义容斥/二项式反演

    LINK:游戏 还是过于弱鸡 没看出来是个二项式反演,虽然学过一遍 但印象不深刻. 二项式反演:有两种形式 一种是以恰好和至多的转换 一种是恰好和至少得转换. 设\(f_i\)表示至多的方案数 \(g ...

  4. NOI 2017 整数(线段树)

    题意 https://loj.ac/problem/2302 思路 拆分成每个二进制位的加减来考虑,维护那个整数的二进制位.不难发现,进位就是找右边第一个 \(0\) 的位置,并将其赋值为 \(1\) ...

  5. [NOI 2017]蔬菜

    Description 题库链接 小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 \(n\) 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各方面因素,设计合理的销售方 ...

  6. [NOI 2017]整数

    Description 题库链接 P 博士将他的计算任务抽象为对一个整数的操作. 具体来说,有一个整数 \(x\) ,一开始为 \(0\) . 接下来有 \(n\) 个操作,每个操作都是以下两种类型中 ...

  7. [NOI 2017]蚯蚓排队

    Description 题库链接 蚯蚓幼儿园有 \(n\) 只蚯蚓.幼儿园园长神刀手为了管理方便,时常让这些蚯蚓们列队表演. 所有蚯蚓用从 \(1\) 到 \(n\) 的连续正整数编号.每只蚯蚓的长度 ...

  8. NOI 2017 Day1 题解

    被虐爆了... T1 整数 题目传送门 Description 有一个整数 \(x\),有 \(n\) 此操作,每次操作为以下两种情况: 给出 \(a,b\),将 \(x\) 加上 \(a\times ...

  9. (转)2-SAT小结

    2-sat小结 原文作者:老K 原文传送门 2-sat是什么 一类问题是这样的: (两个符号的意思 \(\lor \ or,\land \ and\)) 有n个布尔变量,现在对它们做出限制,比如\(a ...

随机推荐

  1. 提交操作自动遮蔽实现之ajax

    有时候,我们期望一些提交操作自动增加遮蔽效果,提交成功时自动去除遮蔽. 方案: 1. 提交前增加遮蔽逻辑,成功后增加去除遮蔽逻辑,但是不够智能 2.通过ajax拦截,实现自动添加\去除遮蔽效果 aja ...

  2. Scrum冲刺阶段2

    成员今日完成的任务 人员 任务 何承华 后端设计 陈宇 后端设计 丁培辉 后端设计 温志铭 主页面的设计 杨宇潇 主页面的设计 张主强 服务器构建 成员遇到的问题 人员 问题 何承华 暂无 陈宇 暂无 ...

  3. Linux 第五天

    网络命令 1)write 给在线用户发信息(需按Crtl+D保存结束,w命令可看在线用户) 语法:write 用户名 2)wall 发广播信息 英文原意:write all 语法:wall 信息 3) ...

  4. modal 移除遮盖层

    弹框关闭时 移除遮盖层 $("#modal").bind('hide.bs.modal',function(){ $(".modal-backdrop").re ...

  5. MFC的停靠窗口中插入对话框,在对话框中添加控件并做控件自适应

    单文档程序添加了停靠窗口后,可能会在停靠窗口中添加一些控件.在这里我的做法是在对话框上添加控件并布局,然后将这个对话框插入到停靠窗口中. 步骤 1.插入对话框,在对话框中放入控件(我的为树形控件),并 ...

  6. [预打印]使用vbs给PPT(包括公式)去背景

    原先博客放弃使用,几篇文章搬运过来 在 视图—>宏 内新建宏 '终极版 Sub ReColor() Dim sld As Slide Dim sh As Shape For Each sld I ...

  7. [f]计时器

    // 计时器 function Timer(ele) { this._mStr = ''; this._sStr = ''; this._m = 0; this._s = 0; this._setTi ...

  8. 美团codeM预赛A轮 倒水

    [编程题] 倒水 时间限制:1秒 空间限制:32768K 有一个大水缸,里面水的温度为T单位,体积为C升.另有n杯水(假设每个杯子的容量是无限的),每杯水的温度为t[i]单位,体积为c[i]升. 现在 ...

  9. 调用redis的时候二维码不断刷新的排查

    一.背景和现象. 项目是PHP开发的,点击登录的时候就根据随机数生成了二维码,缓存在了redis.用户用微信扫描了二维码分析出需要请求的链接,然后微信浏览器就请求了服务器,服务器通过了随机数认证.正当 ...

  10. xampp/apache启动失败解决方法

    我的问题是: 9:15:53 AM  [Apache] Error: Apache shutdown unexpectedly.9:15:53 AM  [Apache] This may be due ...