首页 > 其他分享 >P3825 [NOI2017] 游戏 题解

P3825 [NOI2017] 游戏 题解

时间:2023-08-22 15:44:19浏览次数:33  
标签:int 题解 long 枚举 NOI2017 include 取值 P3825

P3825 [NOI2017] 游戏 题解

首先解决没有 x 的情况,这种情况下 每个事件有两种选择,例如 a 可以选择 b, c,所以这就是一个 2-SAT 问题,但是这题比较特殊,除了题目中给的命题,还需要建立原命题的逆否命题所对应的边,最后跑一遍 \(\text{Tarjan}\) 就出解了。

考虑有 \(d\) 个 \(x\) 的情况,\(x\) 有三种取值,不过 \(\text{3-SAT}\) 是 \(\text{NPC}\) 问题,所以考虑大力枚举 \(x\) 的取值,暴力枚举 \(x\) 的三种取值 \(a,b , c\),\(O(3^d(n+m))\)。

会爆炸,考虑优化,可以发现,只需要枚举 \(x\) 的两种取值即可,因为第三种情况已经被包含了,例如 \(x = a\) 意味着 \(B, C\) 的情况被考虑了,\(x = b\),意味着 \(A, C\) 的情况被考虑了,于是这题只需要枚举每个 \(x\) 是 \(a, b\) 即可,时间复杂度:\(O(2^d(n+m))\)。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
//#define int long long
using namespace std;
const int N = 2e5 + 10;
typedef pair<int, int> PII;
typedef long long ll;

int n, d, m;
struct qwq {
    int a, c;
    char b, d;
} q[N], q2[N];
int idx, x[N];
string s, s2;
vector<int> g[N];
void add(int a, int b) { g[a].push_back(b);
// cout << "link: "<< a << ' ' << b << '\n';
 } 

int get(char o, char t) {
    if(o == t) return -1;
    if(o == 'a') return t == 'C';
    if(o == 'b') return t == 'C';
    if(o == 'c') return t == 'B';
}
char back(char o, int t) {
    if(o == 'a') return (t ? 'C' : 'B');
    if(o == 'b') return (t ? 'C' : 'A');
    if(o == 'c') return (t ? 'B' : 'A');
}
#define rev(x) (x > n ? x - n : x + n)
void link(int i) {
    int x = get(s[q[i].a], q[i].b), y = get(s[q[i].c], q[i].d);
    int a = (x ? q[i].a + 1 + n : q[i].a + 1), b = (y ? q[i].c + 1 + n : q[i].c + 1);
//    cout << a << ' ' << b << '\n';
    if(s[q[i].a] - 'a' == q[i].b - 'A') return ;
    else if(s[q[i].c] - 'a' == q[i].d - 'A') add(a, (rev(a)));
    else add(a, b), add(rev(b), rev(a));
}

int dfn[N], low[N], timestamp, scc, id[N], stk[N], top, ins[N];
void tarjan(int u) {
    dfn[u] = low[u] = ++ timestamp, stk[++top] = u, ins[u] = 1;
    for(auto v : g[u]) {
        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]) {
        int y;
        scc ++;
        do {
            y = stk[top --], id[y] = scc, ins[y] = 0;
        } while(y != u);
    }
}

bool flg;
void work(int h) {
    memcpy(q, q2, sizeof q2);
    s = s2, timestamp = 0, scc = 0, top = 0;
    memset(dfn, 0, sizeof dfn);
    for(int i = 1; i <= n * 2; i ++) g[i].clear();
    for(int i = 0; i < idx; i ++)
        if((1 << i) & h) s[x[i + 1]] = 'a';
        else s[x[i + 1]] = 'b';
    for(int i = 1; i <= m; i ++) 
        link(i);
    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 ;
    flg = 1;
    for(int i = 1; i <= n; i ++) {
        if(id[i] < id[i + n]) cout << back(s[i - 1], 0);
        else cout << back(s[i - 1], 1);
    }
    exit(0);
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> d >> s >> m;
    s2 = s;
    for(int i = 0; i < n; i ++) if(s[i] == 'x') x[++ idx] = i;
    for(int i = 1; i <= m; i ++) 
        cin >> q[i].a >> q[i].b >> q[i].c >> q[i].d, q[i].a --, q[i].c --;
    memcpy(q2, q, sizeof q);
    work(0);
    for(int s = 1; s < (1 << idx); s ++) work(s);
    cout << -1 << '\n';
    return 0;
} 

标签:int,题解,long,枚举,NOI2017,include,取值,P3825
From: https://www.cnblogs.com/MoyouSayuki/p/17648669.html

相关文章

  • RTSP/Onvif视频服务器EasyNVR安防视频云平台硬件无法进入服务器的问题解决方案
    EasyNVR是基于RTSP/Onvif协议的视频接入、处理及分发的安防视频云平台,可提供的视频能力包括:设备接入、实时视频直播、录像、云存储、录像回放与检索、告警、级联等,平台可支持将接入的视频流进行全平台、全终端的分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等......
  • Web_PHP_DedeCMS_文章编辑时,回车不换行问题解决;
    解决:在include\ckeditor目录下找到config.js文件,进行如下设置就好:config.autoParagraph=false;config.enterMode=CKEDITOR.ENTER_P;config.shiftEnterMode=CKEDITOR.ENTER_BR;这样每个段落会隔开,在浏览器中查看文章时,会用<p>段落标志,再加上段落样式缩进两字text-indent:......
  • CF1798E Multitest Generator 题解
    题意定义一个序列\(b_1,b_2,b_3,\cdots,b_m\)为\(\texttt{test}\)当且仅当\(b_1=m-1\)。定义一个序列\(b_1,b_2,b_3,\cdots,b_m\)为\(\texttt{multitest}\)当且仅当该序列可以划分为\(b_1\)段子串,且每段子串均为一个\(\texttt{test}\)。现给定一个长度......
  • nginx: 405 not allowed问题解决
    问题背景:第三方跳转我方一个静态页面,该页面在浏览器地址栏输入url链接后可以直接访问,但对方系统跳转时nginx报405 notallowed原因:前后端分离项目,前端采用nginx部署,nginx默认配置是不支持post请求静态资源的,而对方跳转时采用的post请求,所以nginx拦截报405解......
  • Interval GCD 题解 || WHK废物快乐题
    题意给定一个序列,需要对其进行区间加和和查询\(\gcd\)操作。思路首先看到了区间加和,自然想到是直接打懒标记,但是呢。。。\(\gcd\)具有一些特殊性,我们并不能通过向下传递标记的方式维护\(\gcd\)。于是想到昨天Tad讲树状数组区间修改的差分数组方案。我们创建一个数组......
  • 2023 年山东省大学生程序设计竞赛 个人题解
    比赛链接现场赛榜单洛谷重现赛重现赛个人下饭操作太多,后程直接开摆,分数不够理想。这比赛严格来说应该比区域赛简单。不过有几题我挺喜欢的。先发出来,C、D、F、H、J题这几天会填坑。A.Orders点击查看题意简述某工厂收到\(n\)个订单,每个订单形如「在第\(a_i\)天前交......
  • 「NOIP2013」货车运输 题解
    「NOIP2013」货车运输前言这道题算是一个稍有思维难度的MST+LCA题目了。稍微卡了一会(0-88-88-88-100(打表)-100(打表)-100(正解)),开始是打了表过了,后面在DCZ的帮助下正解通过(下面注释提到的一个坑)。题目大意给出一张无向图\(G\),有\(n\)个点和\(m\)个边\((x,y)=z\),找到一......
  • 猴王 题解 || 冷门的 pb_ds 库
    猴王前言虽然很久以前(6月)在我们学并查集的时候QYC就给我们讲了左偏树可以拿来做这道题,但是左偏树作为拓展内容还是稍有难度,最近在gcc中看到pb_ds库,发现非常好用,于是就有了这种偷懒解法。pb_ds库pb_ds库是内置于GCC中的一种拓展标准库,可以在CCF系列比赛中使用。pb......
  • 「NOIP2017 普及组」棋盘 题解
    前言一个绿题,风光啊QwQ题面传送门思路怎么走我们定义一个函数dfs(x,y,coin,can,color)x,y表示坐标,coin表示当前的金币数量,color表示当前坐标的颜色,can表示当前是否能施展魔法。再加一个mp数组记录颜色,-1表示无颜色,0表示红色,1表示黄色为什么不直接使用mp[x][y]获取颜......
  • [CF1790F] Timofey and Black-White Tree 题解
    [CF1790F]TimofeyandBlack-WhiteTree题解题目描述ZYH有一棵\(n\)个节点的树,最初\(c_0\)号节点是黑色,其余均为白色。给定操作序列\(c_1,c_2,\cdots,c_{n-1}\),第\(i\)次操作表示将\(c_i\)号节点染黑。每次操作后,输出距离最近的两个黑点间的距离。两点\(u,v\)间......