P3825 [NOI2017]游戏

题目

P3825 [NOI2017]游戏

做法

\(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\prime\)

难点在处理\(x\)地图上,三进制枚举车,状压一下也能做,理论时间复杂度\(O(3^d 4m)\),卡不满优化一下也能过吧

往更深层考虑??不枚举选哪个了,枚举选地图,其实只用考虑\(A,B\)就行,\(C\)包含在里面了(反正也只要选一辆)

时间复杂度\(O(2^d 4m)\)

My complete code

#include<bits/stdc++.h>
#include<stack>
using namespace std;
typedef int LL;
const LL maxn=1e6;
struct node{
    LL to,next;
}dis[maxn];
stack<LL> sta;
LL num,n,m,k,tim,tot,d;
LL head[maxn],Scc[maxn],low[maxn],dfn[maxn],pos[maxn],x[maxn],y[maxn],visit[maxn];
char s[maxn],p1[maxn],p2[maxn];
inline void Add(LL u,LL v){
    dis[++num]=(node){v,head[u]},head[u]=num;
}
void Tarjan(LL u){
    visit[u]=1; sta.push(u); low[u]=dfn[u]=++tim;
    for(LL i=head[u];i;i=dis[i].next){
        LL v(dis[i].to);
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(visit[v]) low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u]){
        LL now;
        ++tot;
        do{
            now=sta.top(); sta.pop();
            Scc[now]=tot;
            visit[now]=0;
        }while(now!=u);
    }
}
inline bool Check(){
    for(LL i=1;i<=2*n;++i)
        if(!dfn[i]) Tarjan(i);
    for(LL i=1;i<=n;++i)
        if(Scc[i]==Scc[i+n]) return false;
    for(LL i=1;i<=n;++i){
        if(Scc[i]<Scc[i+n]){
            if(s[i]=='A') printf("B");
            else printf("A");
        }else{
            if(s[i]=='C') printf("B");
            else printf("C");
        }
    }return true;
}
inline void First(){
    for(LL i=1;i<=2*n;++i) visit[i]=0;
    for(LL i=1;i<=2*n;++i) low[i]=0;
    for(LL i=1;i<=2*n;++i) dfn[i]=0;
    for(LL i=1;i<=2*n;++i) Scc[i]=0;
    for(LL i=1;i<=2*n;++i) head[i]=0;
    while(sta.size()) sta.pop();
    num=tim=tot=0;
}
inline void Solve(){
    LL up((1<<d)-1),x1,x2,y1,y2;
    for(LL i=0;i<=up;++i){
        First();
        for(LL j=1;j<=d;++j)
            if(((i>>(j-1))&1)==0) s[pos[j]]='A';
            else s[pos[j]]='B';
        for(LL j=1;j<=m;++j){
            if(p1[j]==s[x[j]]) continue;
            if(p2[j]==s[y[j]]){
                if(p1[j]=='C' || (p1[j]=='B' && s[x[j]]=='C'))
                    Add(x[j]+n, x[j]);
                else
                    Add(x[j], x[j]+n);
                continue;
            }
            if(p1[j]=='A' || (p1[j]=='B'&&s[x[j]]=='A')) x1=x[j],x2=x[j]+n;
            else x1=x[j]+n,x2=x[j];
            if(p2[j]=='A' || (p2[j]=='B'&&s[y[j]]=='A')) y1=y[j],y2=y[j]+n;
            else y1=y[j]+n,y2=y[j];
            
            Add(x1,y1);
            Add(y2,x2);
        }
        if(Check()) return;
    }
    printf("-1");
}
int main(){
    scanf("%d%d",&n,&d);
    scanf(" %s",s+1);
    LL cnt(0);
    for(LL i=1;i<=n;++i)
        if(s[i]=='x')
            pos[++cnt]=i;
        else
            s[i]='A'+(s[i]-'a');
    scanf("%d",&m);
    for(LL i=1;i<=m;++i){
        scanf("%d",x+i);
        scanf(" %c",&p1[i]);
        scanf("%d",y+i);
        scanf(" %c",&p2[i]);
    }
    Solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/y2823774827y/p/10350845.html