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

视频链接:D42 2-SAT+二进制枚举 P3825 [NOI2017] 游戏_哔哩哔哩_bilibili

 

 

 

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 Rule{int i,j;char x,y;}R[N]; //规则

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 i,char c,int t){
  return 'A'+(s[i]-'a'+t)%3==c?i:i+n;
}
char put(int i,int t){
  return 'A'+(s[i]-'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 k=0;k<m;k++){
    int i=R[k].i-1,j=R[k].j-1;
    char x=R[k].x,y=R[k].y;
    if(s[i]==x+32) continue; //i不用x车
    if(s[j]==y+32)           //j不用y车
      add(get(i,x,1),get(i,x,2)); //i→i'
    else{
      add(get(i,x,1),get(j,y,1)); //i→j
      add(get(j,y,2),get(i,x,2)); //j'→i'      
    }
  }
  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",&R[i].i,&R[i].x,&R[i].j,&R[i].y);
  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;
}

 

posted @ 2024-08-13 16:19  董晓  阅读(78)  评论(0编辑  收藏  举报