首页 > 其他分享 >D42 2-SAT+二进制枚举 P3825 [NOI2017] 游戏

D42 2-SAT+二进制枚举 P3825 [NOI2017] 游戏

时间:2024-08-13 16:17:09浏览次数:7  
标签:二进制 枚举 NOI2017 D42 include P3825 SAT

视频链接:

 

P3825 [NOI2017] 游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

// 2-SAT+二进制枚举 O(2^8*(n+m))
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=100005;
int head[N],to[N<<1],ne[N<<1],idx;
int dfn[N],low[N],tim,stk[N],top,scc[N],cnt;
int n,d,m,pos[10]; //pos:x位置
char s[N];         //地图
struct OP{int x,y;char A,B;}op[N<<1]; //条件

void add(int a,int b){
  to[++idx]=b,ne[idx]=head[a],head[a]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=ne[i]){
    int y=to[i];
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;)
      scc[y=stk[top--]]=cnt;
  }
}
int get(int x,char c,int t){
  return 'A'+(s[x]-'a'+t)%3==c?x:x+n;
}
char put(int x,int t){
  return 'A'+(s[x]-'a'+t)%3;
}
bool solve(){
  memset(head,0,sizeof head);
  memset(dfn,0,sizeof dfn);
  memset(scc,0,sizeof scc);
  idx=tim=top=cnt=0;
  for(int i=0;i<m;i++){
    int x=op[i].x-1,y=op[i].y-1;
    char A=op[i].A,B=op[i].B;
    if(s[x]!=A+32){
      if(s[y]!=B+32){
        add(get(x,A,1),get(y,B,1)); //A1→B1
        add(get(y,B,2),get(x,A,2)); //B2→A2
      }
      else add(get(x,A,1),get(x,A,2)); //A1→A2
    }
  }
  for(int i=0;i<2*n;i++)if(!dfn[i])tarjan(i);
  for(int i=0;i<n;i++)
    if(scc[i]==scc[i+n]) return false;
  for(int i=0;i<n;i++)
    if(scc[i]<scc[i+n]) putchar(put(i,1));
    else putchar(put(i,2));
  return true;
}
int main(){
  scanf("%d%d %s %d",&n,&d,s,&m);
  for(int i=0;i<m;i++)
    scanf("%d %c %d %c",&op[i].x,&op[i].A,&op[i].y,&op[i].B);
  for(int i=0,j=0;i<n;i++)
    if(s[i]=='x') pos[j++]=i; //x位置
  for(int i=0;i<1<<d;i++){
    for(int j=0;j<d;j++)
      s[pos[j]]=(i>>j&1)?'a':'b'; //x→a或b
    if(solve()) return 0;
  }
  puts("-1"); return 0;
}

 

标签:二进制,枚举,NOI2017,D42,include,P3825,SAT
From: https://www.cnblogs.com/dx123/p/18332032

相关文章

  • G73 线段树+线性基合并 P5607 [Ynoi2013] 无力回天 NOI2017
    视频链接:G73线段树+线性基合并P5607[Ynoi2013]无力回天NOI2017_哔哩哔哩_bilibili   P5607[Ynoi2013]无力回天NOI2017-洛谷|计算机科学教育新生态(luogu.com.cn)//线段树+线性基合并O(n*logn*logv*logv)#include<iostream>#include<cstring>#incl......
  • P3825 [NOI2017] 游戏
    题目大意有四种类型的比赛\(x,a,b,c\),三种赛车(\(A,B,C\))。其中\(x\)的数量为\(d\)。\(x\)表示三种赛车都可以选,\(a\)表示\(A\)种不能选,\(b\)表示\(B\)种不能选,\(c\)表示\(C\)种不能选。现在要比\(n\)场,有\(m\)个限制形如:\(p,f,q,t\)表示如果第\(p\)......
  • 5034. 【NOI2017模拟3.28】B —— 矩阵树定理和拉格朗日插值的结合
    题目大意给你一棵\(n\)(\(n\le50\))个点的树,可以进行不超过\(k\)次操作,每次断掉一条边,再连上一条边,要求树一直是树,求一共有多少种树的形态。思路把题意转换为对于一个\(n\)个点的完全图,是树边的话权值是\(1\),否则是\(x\)。跑一遍矩阵树定理,矩阵树定理求的是一个图所有生......
  • P5607 [Ynoi2013] 无力回天 NOI2017
    [Ynoi2013]无力回天NOI2017-洛谷看到题目可以想到线性基线性基可以做到\(O(\logA)\)加入,\(O(\logA)\)查询,\(O(\log^2A)\)合并考虑直接暴力的用线段树维护每个节点的线性基,可以做到\(O(n\logn\log^2A)\)但有区间修改?差分转单点修,发现线性基\(a_{[l......
  • NOI2017 蔬菜
    传送门NOI的题果然是非常的难且有意思。还有就是推荐一下command_block的题解。这题的题意比较难。题意:有\(n\)种菜,初始每种菜有\(c_i\)个,单价\(a_i\),如果不出售每天会变质\(x_i\)棵。第一次卖这种菜会获得\(s_i\)的奖励。每天至多卖\(m\)个菜。给出\(q\)次询......
  • [AH2017HNOI2017] 礼物(fft)
    [AH2017/HNOI2017]礼物(fft)题目描述我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有\(n\)个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且......
  • #分块,二分#洛谷 5356 [Ynoi2017] 由乃打扑克
    题目支持区间加和区间查询第\(k\)小分析分块之后给每个整块排序,这样修改的时候整块打标记,散块直接分开把需要加的部分暴力加之后归并,就是\(O(\sqrt{n})\)的查询的话,如果只有散块直接归并出结果,否则二分答案,加上小块合并成的整块,相当于是整体二分,就是\(O(\sqrt{n}\log{a_......
  • HNOI2017影魔题解
    HNOI2017影魔对于两种贡献,都只用考虑左边第一个比自己大的,和右边第一个比自己大的数,分别记为\(l_i、r_i\)对于询问一,每个数对\((l_i,r_i)\)构成全部情况对于询问二,可以拆分成\(x=l_i\)时,\(y\in[i+1,r_i-1]\),以及\(y=r_i\)时,\(x\in[l_i+1,i-1]\)我们考虑用扫描线......
  • P5365 SNOI2017 英雄联盟
    P5365SNOI2017英雄联盟基本思路刚洗完澡做的,脑子转不动了。疑似开始自动化思考了,状态转移方程是这一坨\(F[i][j]*=F[i-1][j-k*w[i]]\)事实上根本不对。首先当前的方案数完全没有体现出来,只乘了之前的方案数,而且这是一个最优性问题,不是计数问题,要在两种状况中做出选......
  • P3722 [AH2017/HNOI2017] 影魔
    题目链接Part1先想暴力,对于每次询问,可以直接\(\Theta(n^2)\)枚举数对,用\(ST\)表判断一下,复杂度为\(\Theta(qn^2)\)。发现枚举数对没有前途,考虑\((i,j)\)之间的最大值,发现一个数对产生的贡献只和区间的最大值有关,我们从这个最大值入手。我们把一个数对的贡献看做其区间最......