P3825 [NOI2017] 游戏(构造2-SAT模型)
发布日期:2021-06-30 10:31:58 浏览次数:2 分类:技术文章

本文共 2099 字,大约阅读时间需要 6 分钟。

我原本以为2-SAT只有裸题…太憨了…

说实话刚看到这题我还以是网络流,我是fw把


二者取一模型

先只考虑 x x x地图以外的地图,发现比较特殊

虽然你有三种车,但是除掉不适合的类型就只有两种合适的车

2-SAT一般是解决二者取一问题,那么现在就是从两种合适的车选一个

简化状态

之前的2-SAT每个点的状态都是真/假,现在可是有 A / B / C A/B/C A/B/C三种车啊!!

但是每次游戏只有两种选择

可以把状态抽象为选择第一种合适的车,或者选择第二种合适的车

建图满足限制

现在每次游戏都拆分为了两个点,都适合本次游戏

对于每条限制形如第 i i i场比赛若选 h i h_i hi车,则第 j j j场比赛必选 h j h_j hj

若第 i i i场比赛不适合 h i h_i hi车,忽略即可,本来第 i i i场比赛就不可能选


若第 i i i场比赛适合 h i h_i hi车且第 j j j场比赛不适合 h j h_j hj

那么第 i i i场比赛不能选 h i h_i hi车,建边 h i − > h i ′ h_i->h_i' hi>hi(其中 h i ′ h_i' hi表示另外一种合适车的选择)

表示不能选 h i h_i hi


若第 i i i场比赛适合 h i h_i hi车且第 j j j场比赛适合 h j h_j hj

那么连边 h i − > h j h_i->h_j hi>hj h j ′ − > h i ′ h_j'->h_i' hj>hi,分别表示要么全选,要么全不选


处理特殊地图

上面的建图已经处理的差不多了,但是有一张地图不符合二者取一模型

x地图适用于三种车,三种选择!!不可做。

注意到 d d d不大,直接二进制枚举每张地图用哪两个车,复杂度 O ( 3 d ) O(3^d) O(3d)

但是发现把 A B , A C , B C AB,AC,BC AB,AC,BC都枚举一遍是很浪费的,因为一张地图只会选一辆车

枚举 A B , A C AB,AC AB,AC即可,不管这张地图想选 A , B , C A,B,C A,B,C都是可以满足的,让2-SAT为你挑。

当然,你想枚举 B C , A C BC,AC BC,AC也没关系。

(代码中的点是i,i+1一组的不是i,i+n一组的,稍微注意一下下)

#include 
using namespace std;const int maxn = 1e7+10;struct edge{
int to,nxt;}d[maxn]; int head[maxn],cnt=1;void add(int u,int v){
d[++cnt] = ( edge ){
v,head[u]},head[u] = cnt;}int l[maxn],r[maxn],n,m,D;int dfn[maxn],low[maxn],stac[maxn],vis[maxn],scc[maxn],id,top,sc;char cn[maxn][2],s[maxn],hi[maxn],hj[maxn];void tarjan(int u){
dfn[u] = low[u] = ++id; stac[++top] = u, vis[u] = 1; for(int i=head[u];i;i=d[i].nxt ) {
int v = d[i].to; if( !dfn[v] ) tarjan(v),low[u] = min( low[u],low[v] ); else if( vis[v] ) low[u] = min( low[u],dfn[v] ); } if( dfn[u]==low[u] ) {
sc++; int temp; while( temp = stac[top--] ) {
scc[temp] = sc; vis[temp] = 0; if( u==temp ) break; } }}int solve(int x){
cnt = 1, id = top = sc = 0; for(int i=1;i<=n+n;i++) dfn[i] = low[i] = head[i] = 0; int now = 0; for(int i=1;i<=n;i++) {
if( s[i]=='a' ) cn[i][0] = 'B',cn[i][1] = 'C'; else if( s[i]=='b' ) cn[i][0] = 'A',cn[i][1] = 'C'; else if( s[i]=='c' ) cn[i][0] = 'A',cn[i][1] = 'B'; else {
if( (1<
> l[i] >> hi[i] >> r[i] >> hj[i] ; for(int i=0;i<(1<

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/115439598 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:P3288 [SCOI2014]方伯伯运椰子(流量守恒,分数规划)
下一篇:P6378 [PA2010] Riddle(2-SAT的前缀和优化建图)

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月28日 20时09分09秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

EasyPol-1 2019-04-30
springboot定时器的使用 2019-04-30
freeswitch设置账号密码和端口 /conf/autoload_configs/event_socket.conf.xml 2019-04-30
freeswitch添加坐席/usr/local/freeswitch/conf/directory/default 2019-04-30
JavaScript原生开关灯效果 2019-04-30
企业邮箱如何申请注册,邮箱申请如何免费注册? 2019-04-30
微信企业邮箱,手机邮箱格式地址怎么写? 2019-04-30
公司如何申请企业邮箱,公司邮箱怎么申请,公司企业邮箱哪个好? 2019-04-30
电子邮箱账号怎么申请,怎样申请邮箱账号呢 2019-04-30
邮箱怎么发邮件,邮件发信量多少,职场新人怎么发汇报邮件呢? 2019-04-30
企业邮箱注册申请流程,企业邮箱怎么注册账号? 2019-04-30
安全邮箱,企业邮箱哪个好?安全电子邮箱申请 2019-04-30
什么是公司邮箱,如何申请公司邮箱,公司邮箱怎么申请? 2019-04-30
163邮箱域名大全,163邮箱注册申请全流程详解! 2019-04-30
电子邮箱账号申请注册,公司邮件系统哪个好?工作邮箱哪个好? 2019-04-30
怎么申请支持微信登录的企业电子邮箱 2019-04-30
163个人电子邮箱如何申请,邮箱账号都有什么格式你知道吗 2019-04-30
微信企业邮箱登录人口,企业邮箱登陆登录入口 2019-04-30
什么是企业邮箱,如何申请企业邮箱,企业邮箱一年多少钱? 2019-04-30
外贸邮箱选择,外贸企业邮箱注册,海外邮箱申请 2019-04-30