~~~题面~~~

题解:

  首先观察到,如果没有x的话,这就是一个2-sat问题。

  建图方式:对于限制d1 c1 d2 c2,其中d1, d2分别代表比赛编号,c1, c2代表出场的赛车。

  1,如果d1不能选c1,那么该限制是不会起到作用的,所以不连边。

  2,否则如果d2不能选c2,那么意味这d1-c1不能被选,所以连d1-c1 --- > d1-c2的边,表示必须取d1-c2。

  3,否则都可以选,所以连d1-c1 ---> d2-c2 , d1-c2 ---> d2-c1.

  跑tarjan求强连通分量即可。

  

  那么有x应该怎么做?

  观察到对于一组数据,x最多有8场,所以3^8枚举每场x的比赛是abc中的哪种(不选哪辆车),然后在跑2-sat即可。

  这里输出方案可以不用反向建边+拓扑排序,因为栈是后进先出,所以先出栈的点刚好是反向建边+拓扑排序后先遇到的点,因此只需要记录每个点所在的联通块编号,然后对于每场比赛选择联通块编号小的方案输出即可。

  题目数据极水,A了也不一定是正确代码,请特别注意检查代码正确性。(如果你发现我有哪里错了也可以告诉我QAQ)

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 300100
#define ac 1000000 int n, d, timer, all, m;
int s[AC], dfn[AC], low[ac], belong[ac], d1[AC], c1[AC], d2[AC], c2[AC];
int sta[AC], top;
int Head[AC], Next[ac], date[ac], tot;
char ss[AC];
bool flag, z[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = * x + c - '', c = getchar();
return x;
} inline void upmin(int &a, int b)
{
if(b < a) a = b;
} inline void add(int f, int w)
{
date[++tot] = w, Next[tot] = Head[f], Head[f] = tot;
//printf("%d ---> %d\n", f, w);
} void tarjan(int x)
{
int now;
dfn[x] = low[x] = ++ timer, sta[++top] = x, z[x] = true;
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(!dfn[now])
{
tarjan(now);
upmin(low[x], low[now]);
}
else if(z[now]) upmin(low[x], low[now]);//已经出栈的无需考虑
}
if(low[x] == dfn[x])
{
++all;
while()
{
now = sta[top--], belong[now] = all, z[now] = false;//标记出栈
if(now == x) break;
}
}
} void init()
{
tot = all = timer = ;
memset(Head, , sizeof(Head));
memset(dfn, , sizeof(dfn));
memset(z, , sizeof(z));
} inline int get(int x, int color)
{
if(s[x] == color) return ;//不合法
if(s[x] == ) return x * + color - ;
else if(s[x] == ) return x * + ((color == ) ? : );
else return x * + color - ;
} void build()
{
init();
for(R i = ; i <= m; i ++)
{
int x = get(d1[i], c1[i]), y = get(d2[i], c2[i]);
if(x)
{
if(y) add(x, y), add(y ^ , x ^ );
else add(x, x ^ );
}
}
int b = n * + ;
for(R i = ; i <= b; i ++)
if(!dfn[i]) tarjan(i);
for(R i = ; i <= b; i += )//error !!!到b
if(belong[i] == belong[i ^ ]) return ;
for(R i = ; i <= n; i ++)
{
int x = i * ;
if(s[i] == ) putchar(belong[x] < belong[x ^ ] ? 'B' : 'C');
else if(s[i] == ) putchar(belong[x] < belong[x ^ ] ? 'A' : 'C');
else putchar(belong[x] < belong[x ^ ] ? 'A' : 'B');
}
flag = true;
} void pre()
{
char ch;
n = read(), d = read();
scanf("%s", ss + );
for(R i = ; i <= n; i ++)
if(ss[i] != 'x') s[i] = ss[i] - 'a' + ;
m = read();
for(R i = ; i <= m; i ++)
{
d1[i] = read(), cin >> ch, c1[i] = ch - 'A' + ;
d2[i] = read(), cin >> ch, c2[i] = ch - 'A' + ;
}
} void dfs(int x)
{
if(flag) return ;
if(x > n)
{
build();
return ;
}
if(!s[x])
{
s[x] = , dfs(x + );
s[x] = , dfs(x + );
s[x] = , dfs(x + );
s[x] = ;
}
else dfs(x + );
} int main()
{
freopen("in.in","r",stdin);
pre();
dfs();
if(!flag) printf("-1");
fclose(stdin);
return ;
}

最新文章

  1. 使用四元数解决万向节锁(Gimbal Lock)问题
  2. ASP.NET Core 开发-中间件(Middleware)
  3. ireport制作小技巧&lt;Reproduce&gt;
  4. phalcon: 多模块多表查找,多表sql
  5. JPA使用入门
  6. Python开发入门与实战20-微信开发配置
  7. java文件编译及运行
  8. SQL Server分布式数据库技术(LinkedServer,CT,SSB)
  9. LeetCode Count Primes 求素数个数(埃拉托色尼筛选法)
  10. 判断手机电脑微信 js
  11. POST与GET
  12. JVM GC-----垃圾回收算法
  13. 「Python」为什么Python里面,整除的结果会是小数?
  14. python基础15下_迭代器_生成器
  15. linux下后台启动springboot项目
  16. Python全栈开发记录_第二篇(文件操作及三级菜单栏增删改查)
  17. android 活动的生命周期
  18. 无视编码都统一转成unicode 然后截断 例如 。“发发发发发发” 操作之后显示为 “发发发发...”
  19. zabbix 安装时 到第三步时 database type 没有mysql选项
  20. pdo sqlserver

热门文章

  1. php+高德地图webapi 高德jsapi 实现 当前位置与目标位置距离 并按照距离排序(坐标逆转换)
  2. mysql新增和更新表从已有数据库里面获取的sql语句
  3. Hadoop参数调优
  4. 2.3 进程控制之exec函数族
  5. Python的scrapy之爬取豆瓣影评和排名
  6. python学习——函数
  7. 函数:引用file类对象及io类对象作为参数打印文本及显示文本
  8. 006---Python基本数据类型--集合
  9. python学习之函数基础
  10. 10-mongodb启动错误