Description

Solution

首先我们发现一个位置如果不是 \('x'\),那么就只有两种选择
而 \('x'\) 的个数小于等于 \(8\),直接枚举是哪个就好了

然后就是 \(2-sat\) 连边:
设一个点 \(i\) 的对立点为 \(i'\)
如果 \(a[i]=h[i]\),那么就可以直接忽略这个限制
如果 \(a[j]=h[j]\),那么 \(i\) 就不能选 \(a[i]\),为了保证这个限制直接连边 \((i,i')\) 就好了
如果上述两种情况都不是,那么直接连 \((i,j),(j',i')\) 就好了

值得注意的是:
\(2-sat\) 如果没有字典序最小的要求,可以直接 \(tarjan\) \(O(n)\) 的判断是否合法
方法就是判断对立点是否在同一强连通分量里即可

输出方案(拓扑排序贪心):
正向贪心会有后效性
把缩点之后的 \(DAG\) 的边反向,发现一个点 \(i\) 选了之后,拓扑序在 \(i'\) 之后的点就都不可以选了
每一次选了 \(i\) 之后,就把 \(i'\) 打上标记即可,就不拿有标记的点删边了

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,D,m,lis[N],fr[N],tr[N];char s[N],a[N],b[N];
int head[N],nxt[N*2],to[N*2],num=1,in[N];
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
int dfn[N],low[N],DFN=0,st[N],top,sum,be[N];bool inst[N],vis[N],fc[N];
vector<int>v[N],sc[N];vector<int>::iterator it;
inline void Clear(){num=1;DFN=sum=top=0;for(register int i=0;i<N;i++)vector<int>().swap(sc[i]),head[i]=low[i]=dfn[i]=inst[i]=0;
}
inline int id(int i,char j){if(s[i]=='a'){if(j=='b')return i;return i+n;}if(s[i]=='b'){if(j=='a')return i;return i+n;}if(j=='a')return i;return i+n;
}
inline int f(int x){return x>n?x-n:x+n;}
inline void tarjan(int x){low[x]=dfn[x]=++DFN;inst[x]=1;st[++top]=x;for(int i=head[x],u;i;i=nxt[i]){if(!dfn[u=to[i]])tarjan(u),low[x]=min(low[x],low[u]);else if(inst[u])low[x]=min(low[x],dfn[u]);}if(low[x]==dfn[x]){int v;sum++;do{v=st[top--];be[v]=sum;inst[v]=0;sc[sum].push_back(v);}while(top && v!=x);}
}
inline void Cliear(){for(register int i=0;i<N;i++)vector<int>().swap(v[i]),in[i]=vis[i]=fc[i]=0;
}
inline void solve(){Clear();for(int i=1;i<=m;i++){if(s[fr[i]]==a[i])continue;if(s[tr[i]]==b[i])link(id(fr[i],a[i]),f(id(fr[i],a[i])));else{int x=id(fr[i],a[i]),y=id(tr[i],b[i]);link(x,y);link(f(y),f(x));}}for(int i=1,li=n*2;i<=li;i++)if(!dfn[i])tarjan(i);for(int i=1;i<=n;i++)if(be[i]==be[i+n])return ;Cliear();for(int i=1,li=n*2;i<=li;i++)for(int j=head[i];j;j=nxt[j]){int u=to[j];if(be[u]==be[i])continue;v[be[u]].push_back(be[i]);in[be[i]]++;}queue<int>Q;for(int i=1;i<=sum;i++)if(!in[i])Q.push(i);while(!Q.empty()){int x=Q.front();Q.pop();if(vis[x])continue;fc[x]=1;for(it=sc[x].begin();it!=sc[x].end();++it)vis[be[f(*it)]]=1;for(it=v[x].begin();it!=v[x].end();++it)if(!(--in[*it]))Q.push(*it);}for(int i=1;i<=n;i++){if(fc[be[i]]){if(s[i]=='a')putchar('B');else putchar('A');}else{if(s[i]=='c')putchar('B');else putchar('C');}}exit(0);
}
inline void dfs(int x){if(x==D+1){solve();return ;}s[lis[x]]='a';dfs(x+1);s[lis[x]]='b';dfs(x+1);
}
int main(){freopen("pp.in","r",stdin);freopen("pp.out","w",stdout);scanf("%d%d%s",&n,&D,s+1);for(int i=1,j=0;i<=n;i++)if(s[i]=='x')lis[++j]=i;scanf("%d",&m);char p1[2],p2[2];for(int i=1;i<=m;i++){scanf("%d%s%d%s",&fr[i],p1,&tr[i],p2);a[i]=p1[0]+32;b[i]=p2[0]+32;}dfs(1);puts("-1");return 0;
}

转载于:https://www.cnblogs.com/Yuzao/p/8591195.html

bzoj 4945: [Noi2017]游戏相关推荐

  1. P3825 [NOI2017]游戏

    P3825 [NOI2017]游戏 题目描述 小 L 计划进行n场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母A.B.C表示.地图一共有四 ...

  2. BZOJ P4554 [Tjoi2016Heoi2016]游戏

    BZOJ P4554 [Tjoi2016&Heoi2016]游戏 题目 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个 ...

  3. [NOI2017]游戏(2-SAT)

    这是约半年前写的题解了,就搬过来吧 感觉这是NOI2017最水的一题(当然我还是不会2333),因为是一道裸的2-SAT.我就是看着这道题学的2-SAT 算法一:暴力枚举.对于abc二进制枚举,对于x ...

  4. BZOJ 1443: [JSOI2009]游戏Game

    1443: [JSOI2009]游戏Game Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1077  Solved: 484 [Submit][S ...

  5. bzoj 4515: [Sdoi2016]游戏

    Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,Alice 会 ...

  6. BZOJ 1854: [Scoi2010]游戏( 二分图最大匹配 )

    匈牙利算法..从1~10000依次找增广路, 找不到就停止, 输出答案. --------------------------------------------------------------- ...

  7. [BZOJ] 1025 [SCOI2009]游戏

    Time Limit: 1 Sec Memory Limit: 162 MB Submit: 2700 Solved: 1774 [Submit][Status][Discuss] Descripti ...

  8. BZOJ 1025: [SCOI2009]游戏

    1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2471  Solved: 1615 [Submit][Statu ...

  9. bzoj 1854: [Scoi2010]游戏(并查集)

    1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 5265  Solved: 2101 [Submit][Statu ...

最新文章

  1. 《统计学》学习笔记之参数估计
  2. CPU的高速缓存存储器知识整理
  3. 前端学习(1272):路由的基本概念和说明
  4. Android开发之自定义的ProgressDialog
  5. Hadoop基础--HDFS/Yarn/MapReduce概述
  6. STM32液晶显示HT1621驱动原理及程序代码
  7. mysql的字段为bit时,插入数据报Data too long
  8. 一个免费、大小仅几MB但超好用的卸载工具——Geek Uninstaller
  9. 仿《91创业网》网站源码 招商加盟致富商机网站 帝国cms模版+采集
  10. 斯坦福大学自然语言处理第四课“语言模型(Language Modeling)
  11. html5 视频缩略图,应用canvas获取video的缩略图
  12. ps换背景操作,巨简单
  13. Android之Fragment回退栈详解
  14. 16.[STM32]从原理开始带你了解DS18B20温度传感器-四位数码管显示温度
  15. QT控件学习:QInputDialog
  16. Java学习之多态二
  17. 多路径路由算法选择(2)——回顾传统的动态路由协议(RIP、OSPF、BGP、IGRP、EIGRP、IS-IS)
  18. 在vscode中加参数调试-python
  19. C++ - std::shared_ptr::get
  20. Unity教程:URP渲染管线实战教程系列【1】

热门文章

  1. 正则验证车牌号码,包括新能源车牌
  2. 模拟电路技术之基础知识(八)
  3. 有关c++中const用法
  4. 【简明教程】windows下xgboost安装到python
  5. 多线程生成随机数组+双线程归并排序(C++实现)
  6. xshell安装mysql步骤_数据库Mysql与禅道安装
  7. 【前端学习日记】利用Vue实现跑马灯的效果
  8. webdriver 获取页面response
  9. 技术管理:带人和团队管理
  10. puppet 工作原理