P3825 [NOI2017] 游戏 题解
P3825 [NOI2017] 游戏
对于,有三种选择,不符合,因此靠枚举为来变为,但是只需要枚举任意两个即可,因为枚举为,则可选,枚举则可选,三种情况都覆盖
对于建边:
若,但是不合法,则无视
若,但是不合法,则,这样就不会选(非法情况的处理方式)
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
int to,nxt;
}edge[N<<1];
struct In
{
int a,b;
char x,y;
}in[N];
int head[N<<1],dfn[N<<1],low[N<<1],belong[N<<1];
bool vis[N<<1];
int a[N],bits[N];
int T=1,n,d,m,ecnt,bcnt,tcnt;
stack<int> stk;
void Add(int u,int v)
{
edge[++ecnt]=(Edge){v,head[u]};
head[u]=ecnt;
}
void Tarjan(int u)
{
dfn[u]=low[u]=++tcnt;
vis[u]=1;
stk.push(u);
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else
if(vis[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int v;
++bcnt;
do
{
v=stk.top();
stk.pop();
vis[v]=0;
belong[v]=bcnt;
}while(u!=v);
}
}
bool Two_sat()
{
for(int i=1;i<=2*n;++i)
if(!dfn[i])
Tarjan(i);
for(int i=1;i<=n;i++)
if(belong[i]==belong[i+n])
return 0;
return 1;
}
void Init()
{
memset(vis,0,sizeof(vis));
memset(belong,0x3f,sizeof(belong));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(head,0,sizeof(head));
while(!stk.empty())
stk.pop();
tcnt=bcnt=ecnt=0;
}
bool Solve()
{
scanf("%lld%lld",&n,&d);
string s;
cin>>s;s=" "+s;
int cnt=0;
for(int i=1;i<s.size();++i)
if(s[i]=='x')
a[i]=cnt++;
scanf("%lld",&m);
for(int i=1;i<=m;++i)
scanf("%lld %c %lld %c",&in[i].a,&in[i].x,&in[i].b,&in[i].y);
for(int now=0;now<(1<<d);++now)
{
Init();
for(int i=1;i<=m;++i)
{
int na=in[i].x-'A',nb=in[i].y-'A';
int l=in[i].a,r=in[i].b;
if(s[in[i].a]=='x')
{
if(now&(1<<a[in[i].a]))
{
if(na==1)
continue;
if(na==2)
l+=n;
}
else
{
if(na==2)
continue;
if(na==1)
l+=n;
}
}
else
{
if((s[in[i].a]-'a')==na)
continue;
if(s[in[i].a]=='a')
if(na==2)
l+=n;
if(s[in[i].a]=='b')
if(na==2)
l+=n;
if(s[in[i].a]=='c')
if(na==1)
l+=n;
}
if(s[in[i].b]=='x')
{
if(now&(1<<a[in[i].b]))
{
if(nb==1)
{
Add(l,(l==in[i].a)?(l+n):(l-n));
continue;
}
if(nb==2)
r+=n;
}
else
{
if(nb==2)
{
Add(l,(l==in[i].a)?(l+n):(l-n));
continue;
}
if(nb==1)
r+=n;
}
}
else
{
if((s[in[i].b]-'a')==nb)
{
Add(l,(l==in[i].a)?(l+n):(l-n));
continue;
}
if(s[in[i].b]=='a')
if(nb==2)
r+=n;
if(s[in[i].b]=='b')
if(nb==2)
r+=n;
if(s[in[i].b]=='c')
if(nb==1)
r+=n;
}
Add(l,r);
if(l==in[i].a)
l+=n;
else
l-=n;
if(r==in[i].b)
r+=n;
else
r-=n;
Add(r,l);
}
if(Two_sat())
{
for(int i=1;i<=n;++i)
{
if(s[i]=='x')
{
if(now&(1<<a[i]))
{
if(belong[i]<belong[i+n])
printf("A");
else
printf("C");
}
else
{
if(belong[i]<belong[i+n])
printf("A");
else
printf("B");
}
}
if(s[i]=='a')
{
if(belong[i]<belong[i+n])
printf("B");
else
printf("C");
}
if(s[i]=='b')
{
if(belong[i]<belong[i+n])
printf("A");
else
printf("C");
}
if(s[i]=='c')
{
if(belong[i]<belong[i+n])
printf("A");
else
printf("B");
}
}
printf("\n");
return 1;
}
}
return 0;
}
signed main()
{
//scanf("%lld",&T);
while(T--)
if(!Solve())
printf("-1\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】