[NOI2017]游戏

题目

来复习\(\text{2-sat}\)

首先对于\(\operatorname{'a'},\rm{'b'},\rm{'c'}\)这三种地图,能放在上面的车只有两种

但是对于\(\rm{'x'}\)能放三种车,变成一个\(\text{3-sat}\)

众所周知\(\text{3-sat}\)只能搜索,于是我们爆搜这个位置放什么车

剩下的我们还是直接用\(\text{2-sat}\)来判定

对于一组限制\(u,h_i,v,h_j\),如果\(u\)上不能放\(h_i\)这辆车,那么这个操作就不用处理了

如果\(v\)上不能放\(h_j\)这辆车,那么就让\(u->u'\),表示一旦选择\(u\)就不合法了

否则我们就正常连边,连\(u->v\),表示选择\(h_i\)就必须选\(h_j\)最重要的是,根据对称性,我们还得连\(v'->u'\),表示不选\(h_j\)就不能选\(h_i\)

这样做的复杂度是\(O(3^d(n+m))\) ,不大可行

考虑我们爆搜的时候不搜\('x'\)放什么车了,改为搜\('x'\)不放什么车,不放\(A\)车,那么就能放\(B\)车和\(C\)车;不放\(B\)车就能放\(A\)车和\(C\)车;所以我们只搜这个位置填成\(a\)还是\(b\)就把三种情况都计算了

于是复杂度\(O(2^d(n+m))\)

代码

#include<bits/stdc++.h>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=1e5+5;
char S[maxn],opv[maxn],opu[maxn];
struct E{int v,nxt;}e[maxn*3];
int u[maxn],v[maxn],tot,pos[15];
int head[maxn],n,m,num,d,__,top,cnt;
int dfn[maxn],col[maxn],low[maxn],st[maxn],f[maxn],id[2][maxn];
inline void add(int x,int y) {
    e[++num].v=y;e[num].nxt=head[x];head[x]=num;
}
void tarjan(int x) {
    dfn[x]=low[x]=++__,f[x]=1,st[++top]=x;
    for(re int i=head[x];i;i=e[i].nxt) 
    if(!dfn[e[i].v]) tarjan(e[i].v),low[x]=min(low[x],low[e[i].v]);
    else if(f[e[i].v]) low[x]=min(low[x],dfn[e[i].v]);
    if(dfn[x]==low[x]) {
        ++cnt;int now;
        do{now=st[top--];col[now]=cnt;f[now]=0;}while(now!=x);
    }
}
inline int getid(int i,char c) {
    if(S[i]==c+'a'-'A') return -1;
    if(S[i]=='a') return c=='B'?0:1;
    if(S[i]=='b') return c=='C'?0:1;
    if(S[i]=='c') return c=='A'?0:1;
}
inline void put(int i,int c) {
    if(S[i]=='a') putchar(c?'C':'B');
    if(S[i]=='b') putchar(c?'A':'C');
    if(S[i]=='c') putchar(c?'B':'A');
}
inline void solve() {
    cnt=__=0;num=0;memset(head,0,sizeof(head));top=0;
    memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
    memset(col,0,sizeof(col));memset(f,0,sizeof(f));
    for(re int i=1;i<=m;i++) {
        int x=getid(u[i],opu[i]);
        if(x==-1) continue;
        int y=getid(v[i],opv[i]);
        if(y==-1) {add(id[x][u[i]],id[x^1][u[i]]);continue;}
        add(id[x][u[i]],id[y][v[i]]);
        add(id[y^1][v[i]],id[x^1][u[i]]);
    }
    for(re int i=1;i<=n+n;i++) if(!dfn[i]) tarjan(i);
    for(re int i=1;i<=n;i++) if(col[i]==col[i+n]) return;
    for(re int i=1;i<=n;i++) 
        if(col[i]<col[i+n]) put(i,0);else put(i,1);
    exit(0);
}
void dfs(int x) {
    if(x==d+1) {solve();return;}
    S[pos[x]]='a';dfs(x+1);
    S[pos[x]]='b';dfs(x+1);
}
int main() {
    n=read();d=read(),scanf("%s",S+1);m=read();
    for(re int i=1;i<=m;i++) {
        u[i]=read();std::cin>>opu[i];
        v[i]=read();std::cin>>opv[i];
    }
    for(re int i=1;i<=n;i++) id[0][i]=i,id[1][i]=i+n;
    for(re int i=1;i<=n;i++) if(S[i]=='x') pos[++tot]=i;
    dfs(1);puts("-1");return 0;
}

转载于:https://www.cnblogs.com/asuldb/p/11563233.html

内容概要:本文档主要介绍了Intel Edge Peak (EP) 解决方案,涵盖从零到边缘高峰的软件配置和服务管理。EP解决方案旨在简化客户的入门门槛,提供一系列工具和服务,包括Edge Software Provisioner (ESP),用于构建和缓存操作系统镜像和软件栈;Device Management System (DMS),用于远程集群或本地集群管理;以及Autonomous Clustering for the Edge (ACE),用于自动化边缘集群的创建和管理。文档详细描述了从软件发布、设备制造、运输、安装到最终设备激活的全过程,并强调了在不同应用场景(如公共设施、工业厂房、海上油井和移动医院)下的具体部署步骤和技术细节。此外,文档还探讨了安全设备注册(FDO)、集群管理、密钥轮换和备份等关键操作。 适合人群:具备一定IT基础设施和边缘计算基础知识的技术人员,特别是负责边缘设备部署和管理的系统集成商和运维人员。 使用场景及目标:①帮助系统集成商和客户简化边缘设备的初始配置和后续管理;②确保设备在不同网络环境下的安全启动和注册;③支持大规模边缘设备的自动化集群管理和应用程序编排;④提供详细的密钥管理和集群维护指南,确保系统的长期稳定运行。 其他说明:本文档是详细描述了Edge Peak技术及其应用案例。文档不仅提供了技术实现的指导,还涵盖了策略配置、安全性和扩展性的考虑,帮助用户全面理解和实施Intel的边缘计算解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值