P3825 [NOI2017]游戏

题意

先不考虑没有\(d\)的限制,此时每场比赛只有两种选择,这是一个典型的\(2-SAT\)模型。

发现\(d\)很小,自然想到枚举每个\(x\)用哪种车,但是\(3^dm\)显然是过不了的。于是我们枚举这个\(x\)不能用那种车,此时我们只需要枚举两个即可,因为此时三种车\(ABC\)都被放到\(x\)上判断过了。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e5+10;
const int maxd=10;
int n,m,cnt_edge,K,tim,scc,top;
int head[maxn],dfn[maxn],low[maxn],col[maxn],sta[maxn],a1[maxm],a2[maxm];
bool state[maxd],vis[maxn];
char s[maxn],t[maxn],b1[maxm],b2[maxm];
vector<int>a;
struct edge{int to,nxt;}e[maxm<<1];
inline int change1(int pos,char x)
{
    if(t[pos]=='a')return x=='C';
    if(t[pos]=='b')return x=='C';
    if(t[pos]=='c')return x=='B';
    return 2333;
}
inline char change2(int pos,int x)
{
    if(t[pos]=='a')return x?'C':'B';
    if(t[pos]=='b')return x?'C':'A';
    if(t[pos]=='c')return x?'B':'A';
    return 'd';
}
inline void add_edge(int u,int v)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++tim;
    sta[++top]=x;vis[x]=1;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]);
        else if(vis[y])low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x])
    {
        int y;scc++;
        do
        {
            y=sta[top--];
            col[y]=scc;vis[y]=0;
        }while(y!=x);
    }
}
inline void clear()
{
    memset(head,0,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(col,0,sizeof(col));
    cnt_edge=scc=top=tim=0;
    for(int i=1;i<=n;i++)t[i]=s[i];
}
inline bool check()
{
    clear();
    for(int i=1;i<=K;i++)t[a[i-1]]=state[i]?'c':'a';
    for(int i=1;i<=m;i++)
    {
        int x=a1[i],y=a2[i];char op1=b1[i],op2=b2[i];
        if(t[x]-'a'==op1-'A')continue;
        if(t[y]-'a'==op2-'A'){add_edge(2*x+change1(x,op1),2*x+(change1(x,op1)^1));continue;}
        add_edge(2*x+change1(x,op1),2*y+change1(y,op2));        
        add_edge(2*y+(change1(y,op2)^1),2*x+(change1(x,op1)^1));
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[2*i])tarjan(2*i);
        if(!dfn[2*i+1])tarjan(2*i+1);
    }
    for(int i=1;i<=n;i++)if(col[2*i]==col[2*i+1])return 0;
    return 1;
}
bool dfs(int dep)
{
    if(dep==K+1)return check();
    state[dep]=0;
    if(dfs(dep+1))return 1;
    state[dep]=1;
    if(dfs(dep+1))return 1;
    return 0;
}
int main()
{
    scanf("%d%d",&n,&K);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)if(s[i]=='x')a.push_back(i);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a1[i]);
        b1[i]=getchar();
        while(b1[i]!='A'&&b1[i]!='B'&&b1[i]!='C')b1[i]=getchar();
        scanf("%d",&a2[i]);
        b2[i]=getchar();
        while(b2[i]!='A'&&b2[i]!='B'&&b2[i]!='C')b2[i]=getchar();
    }
    if(!dfs(1)){puts("-1");return 0;}
    for(int i=1;i<=n;i++)putchar(change2(i,col[2*i]>col[2*i+1]));
    return 0;
}
上一篇:BZOJ 4942: [Noi2017]整数 ZKW线段树


下一篇:我对C#的认知。