「NOI2017」游戏

题目背景

狂野飙车是小 L 最喜欢的游戏。与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略。

题目描述

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

小 L 的赛车有三辆,分别用大写字母ABC表示。地图一共有四种,分别用小写字母xabc表示。其中,赛车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’’(不含双引号)。

输入输出格式

输入格式:

输入第一行包含两个非负整数$n, d$。

输入第二行为一个字符串$S$。$n, d, S$的含义见题目描述,其中$S$包含$n$个字符,且其中恰好$d$个为小写字母$x$。

输入第三行为一个正整数$m$,表示有$m$条用车规则。接下来$m$行,每行包含一个四元组$i, h_i, j, h_j$,其中$i, j$为整数,$h_i, h_j$为字符abc,含义见题目描述。

输出格式:

输出一行。

若无解输出 “-1’’(不含双引号)。

若有解,则包含一个长度为$n$的仅包含大写字母ABC的字符串,表示小 L 在这$n$场游戏中如何安排赛车的使用。如果存在多组解,输出其中任意一组即可。

输入输出样例

输入样例#1:
复制

3 1
xcc
1
1 A 2 B
输出样例#1:
复制

ABA

说明

【样例1解释】

小 L 计划进行$3$场游戏,其中第$1$场的地图类型是x,适合所有赛车,第$2$场和第$3$场的地图是c,不适合赛车C

小 L 希望:若第$1$场游戏使用赛车A,则第$2$场游戏使用赛车B。那么为这$3$场游戏分别安排赛车ABA可以满足所有条件。若依次为$3$场游戏安排赛车为BBBBAA时,也可以满足所有条件,也被视为正确答案。但依次安排赛车为AABABC时,因为不能满足所有条件,所以不被视为正确答案。

xyz32768的题解

\(NOI2017 Day2 T1\)。\(2-SAT\)。

可以发现,除了x地图之外,其余的地图只适合两种赛车。而在这里,我们先假设所有的地图都适合且只适合两种赛车,这样就是\(2-SAT\)裸题了。

对于每场游戏用两个点\(i\)和\(i'\),分别表示第\(i\)场游戏使用该地图适合的第一种赛车和第二种赛车(举例:如果第\(i\)场游戏的地图不适合A赛车,那么点\(i\)表示第\(i\)场游戏使用B赛车,点\(i'\)表示第\(i\)场游戏使用C赛车)。

对于每个限制条件,设\(u\)为表示「第\(i\)场游戏使用型号为\(hi\)的赛车」的点(在第\(i\)场游戏的地图适合型号为\(hi\)的赛车的情况下),\(v\)为表示「第\(j\)场游戏使用型号为\(hj\)的赛车」的点(在第\(j\)场游戏的地图适合型号为\(hj\)的赛车的情况下),

那么,

如果第\(i\)场游戏的地图不适合型号为\(hi\)的赛车,那么不做任何操作。

如果第\(i\)场游戏的地图适合型号为\(hi\)的赛车,但第\(j\)场游戏的地图不适合型号为\(hj\)的赛车,那么建边\(u->u'\),表示如果第\(i\)场游戏使用了型号为\(hi\)的赛车则一定无解。

如果第\(i\)场游戏的地图适合型号为\(hi\)的赛车,第\(j\)场游戏的地图适合型号为\(hj\)的赛车,那么建边\(u->v\),表示如果第\(i\)场游戏使用了型号为\(hi\)的赛车则第\(j\)场游戏必须使用型号为\(hj\)的赛车,再建边\(v'->u'\),表示如果第\(j\)场游戏不使用型号为\(hj\)的赛车则第\(i\)场游戏不得使用型号为\(hi\)的赛车。

所有边都建完之后跑一遍\(Tarjan\)强连通分量缩点。对于任意一个\(i\),如果\(i\)和\(i'\)在同一个强连通分量里面,那么此时无解。

否则输出方案。\(2-SAT\)输出方案的方法为:先把缩点之后的新图进行拓扑排序,然后判断每个点\(i\),如果\(i\)所在强连通分量的拓扑序在\(i'\)所在的强连通分量的拓扑序之后,那么第\(i\)场游戏使用该地图适合的第一种赛车,否则使用第二种赛车。但是由于\(Tarjan\)求强连通分量就是按拓扑排序的逆序给出的,所以直接使用强连通分量编号判断即可。即如果\(bel[]\)为每个点的所在强连通分量编号,那么判断为:如果\(bel[i]<bel[i']\),那么使用该地图适合的第一种赛车,否则使用第二种赛车。

现在考虑x地图,考虑到只有8张x地图,如果假设它也只适合两种赛车,那么暴力枚举每个x地图不适合赛车A或不适合赛车B(因为不适合赛车A就是适合赛车BC,不适合赛车B就是适合赛车AC,这样就包含了ABC三种赛车),这样每种地图就都只适合两种赛车了。判断时,如果已经枚举遍了所有的\(2^d\)种状态都是无解,则原问题无解,否则输出任意一种方案。

复杂度\(O((n+m)*2^d)\)。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int maxm=5e5+5,maxn=1e5+5,maxe=maxm*2;
co int lst[3][2]={{1,2},{0,2},{0,1}};
int n,D,m,c[maxn][2],pos[15],ban[maxn],ans[maxn];
int head[maxn*2],next[maxe],ver[maxe],tot;
char map[maxn];
struct data {int x,hx,y,hy;}q[maxm];
il void add(int x,int y){
ver[++tot]=y,next[tot]=head[x],head[x]=tot;
}
int dfn[maxn*2],low[maxn*2],tim,stk[maxn*2],top,scc,blg[maxn*2];
bool ins[maxn];
void tarjan(int x){
dfn[x]=low[x]=++tim;
stk[++top]=x,ins[x]=1;
for(int j=head[x];j;j=next[j]){
if(!dfn[ver[j]]) tarjan(ver[j]),low[x]=min(low[x],low[ver[j]]);
else if(ins[ver[j]]) low[x]=min(low[x],dfn[ver[j]]);
}
if(dfn[x]==low[x]){
++scc;
do{
ins[stk[top]]=0;
blg[stk[top]]=scc;
}while(stk[top--]!=x);
}
}
int main(){
read(n),read(D),scanf("%s",::map+1);
read(m);
for(int i=1;i<=m;++i){
static char ch[2];
read(q[i].x);
scanf("%s",ch),q[i].hx=ch[0]-'A';
read(q[i].y);
scanf("%s",ch),q[i].hy=ch[0]-'A';
}
for(int i=1,_d=0;i<=n;++i){
if(::map[i]=='x') pos[++_d]=i;
else{
ban[i]=::map[i]-'a';
c[i][0]=lst[ban[i]][0],c[i][1]=lst[ban[i]][1];
}
}
for(int s=0;s<1<<D;++s){
for(int i=1;i<=D;++i){
ban[pos[i]]=(s>>i-1)&1;
c[pos[i]][0]=lst[ban[pos[i]]][0],c[pos[i]][1]=lst[ban[pos[i]]][1];
}
memset(head,0,sizeof head),tot=0;
for(int i=1;i<=m;++i){
if(ban[q[i].x]==q[i].hx) continue;
if(ban[q[i].y]==q[i].hy){
int a=c[q[i].x][1]==q[i].hx;
add(q[i].x<<1|a,(q[i].x<<1|a)^1);
}
else{
int a=c[q[i].x][1]==q[i].hx,b=c[q[i].y][1]==q[i].hy;
add(q[i].x<<1|a,q[i].y<<1|b);
add((q[i].y<<1|b)^1,(q[i].x<<1|a)^1);
}
}
memset(dfn,0,sizeof dfn),tim=scc=0;
for(int i=2;i<=(n<<1|1);++i)
if(!dfn[i]) tarjan(i);
bool flag=0;
for(int i=1;i<=n;++i){
if(blg[i<<1]==blg[i<<1|1]) {flag=1;break;}
ans[i]=c[i][blg[i<<1|1]<blg[i<<1]];
}
if(flag) continue;
for(int i=1;i<=n;++i) putchar('A'+ans[i]);
return 0;
}
puts("-1");
return 0;
}

LOJ2305 「NOI2017」游戏的更多相关文章

  1. LG3825/BZOJ4945/LOJ2305 「NOI2017」游戏 dfs+2-SAT

    问题描述 LG3825 BZOJ4945 LOJ2305 题解 发现对于每个地图,如果没有\(A,B,C\)地图不可以使用\(a,b,c\),就是一个\(\mathrm{3-SAT}\)问题. 有了这 ...

  2. LOJ_2305_「NOI2017」游戏 _2-sat

    LOJ_2305_「NOI2017」游戏 _2-sat 题意: 给你一个长度为n的字符串S,其中第i个字符为a表示第i个地图只能用B,C两种赛车,为b表示第i个地图只能用A,C两种赛车,为c表示第i个 ...

  3. 「NOI2017」游戏

    「NOI2017」游戏 题目描述 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 \(A\).\(B\).\ ...

  4. loj #2305. 「NOI2017」游戏

    #2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...

  5. 「NOI2017」游戏 解题报告

    「NOI2017」游戏 \(d\)这么小,你考虑直接对\(d\)个东西暴力 枚举\(x\)为\(a\)或\(b\)(\(c\)就不用了,因为\(a,b\)已经包含\(c\))了,剩下的就是个\(2-s ...

  6. loj#2305. 「NOI2017」游戏 2-sat

    链接 https://loj.ac/problem/2305 https://www.luogu.org/problemnew/show/P3825 思路 3-sat神马的就不要想了,NP问题 除去x ...

  7. 【LOJ】 #2305. 「NOI2017」游戏

    题解 枚举x所在的地图的颜色,然后2-SAT建边 如果v所在的地图刚好是不能选的,那么u这边只能选另一种颜色 否则就是u的颜色到v的颜色 v的另一种颜色到u的另一种颜色 代码 #include < ...

  8. 「HNOI2018」游戏

    「HNOI2018」游戏 解题思路 首先没有锁上的门可以缩点缩掉,然后对于一扇锁上的门,如果钥匙在左边,那么右边就永远不可能到达左边,同理如果钥匙在右边,左边就永远不可能到达右边. 然后考虑一个暴力的 ...

  9. LOJ2303 「NOI2017」蚯蚓排队

    「NOI2017」蚯蚓排队 题目描述 蚯蚓幼儿园有$n$只蚯蚓.幼儿园园长神刀手为了管理方便,时常让这些蚯蚓们列队表演. 所有蚯蚓用从$1$到$n$的连续正整数编号.每只蚯蚓的长度可以用一个正整数表示 ...

随机推荐

  1. 在Linux先显示文件

    cat:从第一行开始显示文件内容. tac:从最后一行开始显示内容. nl:显示的时候带行号. more:一页一页显示. less:同more,可以向上翻页. head:显示文件前几行. head - ...

  2. Solr6.5与mysql集成建立索引

    首先在solrconfig.xml(我的是保存在/usr/local/tomcat/solrhome/mycore/conf/下)的<requestHandler name="/sel ...

  3. 1、Codevs 必做:2833、1002、1003、2627、2599

    2833 奇怪的梦境  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description Aiden陷入了一个奇怪的梦境:他被困 ...

  4. 【BZOJ4320】ShangHai2006 Homework 分段+并查集

    [BZOJ4320]ShangHai2006 Homework Description   1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在.    2:在当前的人 ...

  5. MySQL登陆数据库

    下面是几种登陆到MySql数据库的登陆方式代码 1mysql -u root -ppassword 2.mysql -u root -p Enter password:password3.mysql ...

  6. Django 之 缓存机制

    Django 缓存机制 缓存介绍 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候,每一次 ...

  7. emmet缩写格式

    2016年5月30日 10:10 标准网页<!DOCTYPE html> <html lang="zh-CN"> <head> <meta ...

  8. ubuntu防火墙

    开启防火墙 sudo ufw enable 关闭防火墙 sudo ufw disable 查看防火墙状态 sudo utw status

  9. c/c++ 输入输出技巧

    C: 小数的四舍五入问题 小数用 %.xf 输出的话 是会自动四舍五入的 比如说 double e = 2.718, c = 3.141; printf("%.2lf\n", e) ...

  10. Data Structure Linked List: Write a function to get the intersection point of two Linked Lists.

    http://www.geeksforgeeks.org/write-a-function-to-get-the-intersection-point-of-two-linked-lists/ 第一第 ...