BZOJ 4945 NOI2017 游戏 搜索+2-SAT

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4945

 

分析:

  首先考虑没有x的情况,发现有一个明显的推理模型,容易看出来可以用2-SAT做。

  然后考虑有x的情况,发现最多只有8个x,不难想到可以搜索每个x为a,b,c中的哪个然后跑2-SAT。但是算算时间发现会T。

  再仔细分析,发现只需要枚举两种情况就可以了。因为可行的对象已经全部在这两种情况里面包含了!

  发现真的tarjan比另外一个算法快......事实证明另外一个算法(我叫不出名字ORZ)是可以被卡成O(NM)的。(从此入了tarjan的教。。。)

  此题细节令人开心。

  时间复杂度O((N+M)*2^x)。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 #include<vector>
 11 #include<cctype>
 12 using namespace std;
 13 const int maxn=50005;
 14 const int maxm=100005;
 15 
 16 int N,D,M;
 17 char S[maxn];
 18 struct edge{ int to,next; }E[maxm<<1];
 19 struct data{ int i,j; char hi,hj; }da[maxm];
 20 int first[maxn<<1],_first[maxn<<1],np,pos[10],cnt,stk[maxn<<1],top;
 21 int dfn[maxn<<1],sccno[maxn<<1],dfs_clock,scc_cnt,low[maxn<<1];
 22 bool bad[maxn<<1],_bad[maxn<<1];
 23 
 24 void _scanf(int &x)
 25 {
 26     x=0;
 27     char ch=getchar();
 28     while(ch<'0'||ch>'9') ch=getchar();
 29     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
 30 }
 31 void _scanf(char &x)
 32 {
 33     x=getchar();
 34     while(!isalpha(x)) x=getchar();
 35 }
 36 void add_edge(int u,int v,int *f)
 37 {
 38     E[++np]=(edge){v,f[u]};
 39     f[u]=np;
 40 }
 41 int id(int i,char a)
 42 {
 43     if(S[i]=='a') return i*2-(a=='B'?1:0);
 44     return i*2-(a=='A'?1:0);
 45 }
 46 int _id(int i,bool k)
 47 {
 48     if(k) return S[i]=='a'?1:0;
 49     return S[i]=='c'?1:2;
 50 }
 51 void data_in()
 52 {
 53     _scanf(N);_scanf(D);scanf("%s",S+1);_scanf(M);
 54     int a,b; char hi,hj;
 55     for(int i=1;i<=N;i++)
 56         if(S[i]=='x') pos[++cnt]=i;
 57     cnt=0;
 58     for(int i=1;i<=M;i++){
 59         _scanf(a);_scanf(hi);_scanf(b);_scanf(hj);
 60         if(S[a]-hi==32) continue;
 61         if(S[a]=='x'||S[b]=='x'){
 62             da[++cnt]=(data){a,b,hi,hj}; 
 63             continue;
 64         }
 65         if(S[b]-hj==32){ bad[id(a,hi)]=1; continue; }
 66         a=id(a,hi),b=id(b,hj);
 67         add_edge(a,b,first); add_edge((b-1^1)+1,(a-1^1)+1,first);
 68     }
 69 }
 70 void tarjan_scc(int i)
 71 {
 72     if(_bad[i]) return;
 73     dfn[i]=low[i]=++dfs_clock;
 74     stk[++top]=i;
 75     for(int p=_first[i];p;p=E[p].next){
 76         int j=E[p].to;
 77         if(dfn[j]){
 78             if(!sccno[j]) low[i]=min(low[i],dfn[j]);
 79             continue;
 80         }
 81         tarjan_scc(j);
 82         low[i]=min(low[i],low[j]);
 83     }
 84     if(low[i]==dfn[i]){
 85         scc_cnt++;
 86         while(stk[top]!=i) sccno[stk[top--]]=scc_cnt;
 87         sccno[stk[top--]]=scc_cnt;
 88     }
 89 }
 90 bool judge()
 91 {
 92     memset(dfn,0,sizeof(dfn));
 93     memset(sccno,0,sizeof(sccno));
 94     memset(low,0,sizeof(low));
 95     dfs_clock=scc_cnt=top=0;
 96     for(int i=1;i<=N*2;i++)
 97         if(!dfn[i]) tarjan_scc(i);
 98     for(int i=1;i<=N;i++)
 99         if(sccno[i*2-1]==sccno[i*2]) return 0;
100     return 1;
101 }
102 bool run(int i)
103 {
104     if(i>D){
105         memcpy(_first,first,sizeof(first));
106         memcpy(_bad,bad,sizeof(bad));
107         int tmp=np,a,b;
108         for(int k=1;k<=cnt;k++){
109             if(S[da[k].i]-da[k].hi==32) continue;
110             if(S[da[k].j]-da[k].hj==32){ _bad[id(da[k].i,da[k].hi)]=1; continue; }
111             a=id(da[k].i,da[k].hi),b=id(da[k].j,da[k].hj);
112             add_edge(a,b,_first); add_edge((b-1^1)+1,(a-1^1)+1,_first);
113         }
114         np=tmp;
115         return judge();
116     }
117     S[pos[i]]='a'; if(run(i+1)) return 1;
118     S[pos[i]]='b'; if(run(i+1)) return 1;
119     return 0;
120 }
121 void work()
122 {
123     if(!run(1)) printf("%d\n",-1);
124     else{
125         for(int i=1;i<=N;i++){
126             if(!sccno[i*2-1]) putchar('A'+_id(i,0));
127             else if(!sccno[i*2]) putchar('A'+_id(i,1));
128             else if(sccno[i*2]<sccno[i*2-1]) putchar('A'+_id(i,0));
129             else putchar('A'+_id(i,1));
130         }
131         putchar('\n');
132     }
133 }
134 int main()
135 {
136     data_in();
137     work();
138     return 0;
139 }
View Code

 

posted @ 2018-04-07 22:00  KKKorange  阅读(355)  评论(0编辑  收藏  举报