ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2017]游戏

2020-01-15 20:51:10  阅读:310  来源: 互联网

标签:游戏 int dfs NOI2017 比赛 ban include sat


题目链接

题目大意

有n场比赛,每场比赛可以选择A,B,C类型中的一个。

大多数比赛自身有所限制,即不能选择某一个类型(A/B/C)。只有少数(共\(d\)个)没有限制。

除此之外还有\(m\)个限制\((i,h_i,j,h_j)\),表示若第\(i\)场比赛选了\(h_i\),则第\(j\)场比赛必须选\(h_j\)。

解题思路

依赖性的限制,多半是2-sat。

但是有些比赛有3种选择。而3-sat是NP问题。

可以发现\(d\)非常小,所以可以强制要求有3种选择的比赛也有限制。

然后照常建边,跑2-sat即可。

不过尤其坑人的是要输出方案,具体可以见2-sat模板

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 200010
#define M 300010
using namespace std;
int nxt[M<<1],to[M<<1],head[N],cnt;
void add(int u,int v)
{
    nxt[++cnt]=head[u];
    to[cnt]=v;
    head[u]=cnt;
}
int dfn[N],id[N],low[N],idn,uid;
int sta[N],top;
bool in[N];
void tarjan(int u)
{
    dfn[u]=low[u]=++idn;
    sta[top++]=u;
    in[u]=true;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[v],low[u]);
        }
        else if(in[v])low[u]=min(dfn[v],low[u]);
    }
    if(dfn[u]==low[u])
    {
        int v;
        ++uid;
        do{
            v=sta[--top];
            in[v]=false;
            id[v]=uid;
        }
        while(u!=v);
    }
}
int ban[N],n,m;
inline int get_id(int u,int d){return u*3+d;}
bool solve(void)
{
    for(int i=1;i<=(n+1)*3;i++)
    if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++)
    if(id[get_id(i,(ban[i]+1)%3)]==id[get_id(i,(ban[i]+2)%3)]) return false;
    return true;
}
struct Q{
    int l,x,r,y;
}q[M];
int get_nxt(int u,int p){p=(p+1)%3;return ban[u]==p?(p+1)%3:p;}
void work(void)
{
    memset(head,0,sizeof(head));
    cnt=0;
    memset(id,0,sizeof(id));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    uid=top=idn=0;
    for(int i=1;i<=m;i++)
    {
        if(ban[q[i].l]==q[i].x) continue;
        if(ban[q[i].r]==q[i].y){add(get_id(q[i].l,q[i].x),get_id(q[i].l,get_nxt(q[i].l,q[i].x)));continue;}
        add(get_id(q[i].l,q[i].x),get_id(q[i].r,q[i].y));
        add(get_id(q[i].r,get_nxt(q[i].r,q[i].y)),get_id(q[i].l,get_nxt(q[i].l,q[i].x)));
    }
    if(!solve()) return;
    for(int i=1;i<=n;i++)
    {
        int p1=(ban[i]+1)%3;
        int p2=(ban[i]+2)%3;
        if(id[get_id(i,p1)]>id[get_id(i,p2)]) p1=p2;
        putchar('A'+p1);
    }
    exit(0);
}
void dfs(int u)
{
    while(u<=n && ban[u]!=-1) u++;
    if(u>n){work();return;}
    ban[u]=0;
    dfs(u+1);
    ban[u]=1;
    dfs(u+1);
    ban[u]=-1;
}
char str[N];
char a1[3],a2[3];
int main()
{
    int d;
    scanf("%d%d",&n,&d);
    scanf("%s",str+1);
    for(int i=1;i<=n;i++)
    if(str[i]=='x') ban[i]=-1;
    else ban[i]=str[i]-'a';
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%s%d%s",&u,a1,&v,a2);
        q[i]=(Q){u,a1[0]-'A',v,a2[0]-'A'};
    }
    dfs(1);
    printf("-1");
    return 0;
}

标签:游戏,int,dfs,NOI2017,比赛,ban,include,sat
来源: https://www.cnblogs.com/Flying2018/p/12198716.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有