「NOI2017」游戏 解题报告
「NOI2017」游戏
\(d\)这么小,你考虑直接对\(d\)个东西暴力
枚举\(x\)为\(a\)或\(b\)(\(c\)就不用了,因为\(a,b\)已经包含\(c\))了,剩下的就是个\(2-sat\)问题了
但是你发现有个情况是,在若\(A\)即\(B\)时,如果\(B\)被\(ban\)了,那么\(A\)也要被\(ban\)
我们记录一下被\(ban\)的点,然后在球方案的时候判一下(不得不用topo排序了..
但是其实也可以\(A\)连\(\lnot A\),就可以直接比较SCC编号大小搞方案了
Code:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#include <algorithm>
using std::min;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
x=0;char c=gc();
while(!isdigit(c)) c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
}
template <class T>
void reads(T &x)
{
char c=gc();
while(c<'a'||c>'z') c=gc();
x=c-'a'+1;
}
template <class T>
void readb(T &x)
{
char c=gc();
while(c<'A'||c>'Z') c=gc();
x=c-'A'+1;
}
const int N=2e5+10;
int head[N],to[N],Next[N],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
struct _toki
{
int a,b,c,d;
}toki[N];
int n,m,_n,yuu[N][4],ops[N],saki[N];
int val[N],ban[N],Ban[N],q[N],bel[N],opsi[N];
int low[N],dfn[N],in[N],sta[N],tot,dfsclock;
std::vector <int> E[N];
void tarjan(int now)
{
dfn[now]=low[now]=++dfsclock;
in[sta[++tot]=now]=1;
for(int v,i=head[now];i;i=Next[i])
{
if(!dfn[v=to[i]])
{
tarjan(v);
low[now]=min(low[now],low[v]);
}
else if(in[v])
low[now]=min(low[now],dfn[v]);
}
if(low[now]==dfn[now])
{
int k;++_n;
do
{
k=sta[tot--];
in[k]=0;
bel[k]=_n;
}while(now!=k);
}
}
int solve()
{
memset(head,0,sizeof head);cnt=0;
memset(ban,0,sizeof ban);
memset(Ban,0,sizeof Ban);
for(int a,b,c,d,i=1;i<=m;i++)
{
a=toki[i].a,b=toki[i].b,c=toki[i].c,d=toki[i].d;
if(saki[a]==b) continue;
if(saki[c]==d)
{
ban[yuu[a][b]]=1;
continue;
}
add(yuu[a][b],yuu[c][d]);
add(ops[yuu[c][d]],ops[yuu[a][b]]);
}
memset(in,0,sizeof in);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(bel,0,sizeof bel);
memset(opsi,0,sizeof opsi);
_n=dfsclock=0;
for(int i=1;i<=n<<1;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
if(bel[i]==bel[i+n])
return -1;
memset(val,-1,sizeof val);
for(int i=1;i<=_n;i++) E[i].clear();
//int ecnt=0;
for(int u=1;u<=n<<1;u++)
{
for(int v,i=head[u];i;i=Next[i])
if(bel[u]!=bel[v=to[i]])
E[bel[v]].push_back(bel[u]),++in[bel[u]];//++ecnt;
Ban[bel[u]]|=ban[u];
opsi[bel[u]]=bel[ops[u]];
}
int l=1,r=0;
for(int i=1;i<=_n;i++)
if(!in[i]&&!Ban[i])
q[++r]=i;
while(l<=r)
{
int now=q[l++];
if(val[now]==-1) val[now]=0,val[opsi[now]]=1;
for(int v,i=0;i<E[now].size();i++)
{
v=E[now][i];
--in[v];
if(!in[v]&&!Ban[v]) q[++r]=v;
}
}
for(int i=1;i<=n;i++)
if(val[bel[i]]==-1)
return -1;
for(int i=1;i<=n;i++)
{
int x=val[bel[i]];
for(int j=1;j<=3;j++)
{
if(saki[i]!=j)
{
if(!x) putchar('A'+j-1);
--x;
}
}
//puts("");
}
return 0;
}
int main()
{
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
int d,yuy[10];
read(n),read(d);
d=0;
for(int i=1;i<=n;i++)
{
ops[i]=i+n;
ops[i+n]=i;
reads(saki[i]);
if(saki[i]==24)
{
yuy[++d]=i;
continue;
}
int aya=i;
for(int j=1;j<=3;j++)
{
if(saki[i]!=j)
{
yuu[i][j]=aya;
aya+=n;
}
}
}
read(m);
for(int i=1;i<=m;i++) read(toki[i].a),readb(toki[i].b),read(toki[i].c),readb(toki[i].d);
if(!d)
{
if(solve()==-1) puts("-1");
return 0;
}
for(int s=0;s<1<<d;s++)
{
for(int i=1;i<=d;i++)
{
if(!(s>>i-1&1))
{
saki[yuy[i]]=1;
yuu[yuy[i]][2]=yuy[i];
yuu[yuy[i]][3]=yuy[i]+n;
}
else
{
yuu[yuy[i]][1]=yuy[i];
saki[yuy[i]]=2;
yuu[yuy[i]][3]=yuy[i]+n;
}
}
if(~solve()) return 0;
}
puts("-1");
return 0;
}
2019.6.2