P3825-[NOI2017]游戏【2-SAT】

    科技2024-07-15  67

    正题

    题目链接:https://www.luogu.com.cn/problem/P3825


    题目大意

    n n n场比赛,对于场地 a a a不能用赛车 A A A b , c b,c b,c以此类推),对于场地 x x x可以用任何赛车。然后给定 m m m条条件形如 i   I   j   J i\ I\ j\ J i I j J表示在第 i i i场比赛使用赛车 I I I的话那么必须在第 j j j场比赛使用赛车 J J J

    求一组合法安排方案


    解题思路

    因为对于场地 x x x我们有三种选择方法,所以这是一个 3 − S A T 3-SAT 3SAT问题,无法计算。而因为 x x x场地数量很少,我们可以枚举每个场地 x x x使用哪辆车(是场地 a a a还是场地 b b b)即可。

    然后就是很普通的 2 − S A T 2-SAT 2SAT问题了,时间复杂度 O ( 2 d n ) O(2^dn) O(2dn)


    c o d e code code

    #include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define p(n,k) (((n)-1)*6+(k)+1) using namespace std; // 0选a 1不选择a 2选择b 3不选择b 4选择c 5不选择c const int N=5e4*6; struct node{ int to,next; }a[N*8]; struct quee{ int a,b,va,vb; }q[N]; int n,d,m,tot,scc,cnt,ls[N]; int dfn[N],low[N],color[N]; bool ins[N];char s[N]; stack<int> S; void addl(int x,int y,int w){ if(w)addl(y,x,0); a[++tot].to=y; a[tot].next=ls[x]; ls[x]=tot; return; } void tarjan(int x){ dfn[x]=low[x]=++cnt; S.push(x);ins[x]=1; for(int i=ls[x];i;i=a[i].next){ int y=a[i].to; if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]); else if(ins[y])low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ ++scc; while(S.top()!=x){ color[S.top()]=scc; ins[S.top()]=0; S.pop(); } color[S.top()]=scc; ins[S.top()]=0; S.pop(); } return; } bool solve(){ memset(ls,0,sizeof(ls)); memset(dfn,0,sizeof(dfn)); cnt=scc=tot=0; for(int i=1;i<=n;i++){ if(s[i]=='a'){ addl(p(i,0),p(i,1),0);//不能选a addl(p(i,2),p(i,5),1);//选b不选c addl(p(i,4),p(i,3),1);//选c不选b } if(s[i]=='b'){ addl(p(i,2),p(i,3),0);//不能选b addl(p(i,0),p(i,5),1);//选a不选c addl(p(i,4),p(i,1),1);//选c不选a } if(s[i]=='c'){ addl(p(i,4),p(i,5),0);//不能选c addl(p(i,0),p(i,3),1);//选a不选b addl(p(i,2),p(i,1),1);//选b不选a } } for(int i=1;i<=m;i++) {addl(p(q[i].a,q[i].va),p(q[i].b,q[i].vb),0);addl(p(q[i].b,q[i].vb+1),p(q[i].a,q[i].va+1),0);} for(int i=1;i<=n*6;i++) if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++) if(color[p(i,0)]==color[p(i,1)]||color[p(i,2)]==color[p(i,3)]||color[p(i,4)]==color[p(i,5)]){return 0;} for(int i=1;i<=n;i++){ if(color[p(i,0)]<color[p(i,1)])printf("A"); else if(color[p(i,2)]<color[p(i,3)])printf("B"); else if(color[p(i,4)]<color[p(i,5)])printf("C"); } return 1; } int main() { scanf("%d%d",&n,&d); scanf("%s",s+1);d=0; int wz[10]; for(int i=1;i<=n;i++) if(s[i]=='x')wz[++d]=i; scanf("%d",&m); for(int i=1;i<=m;i++){ int a,b,va,vb;char oa[3],ob[3]; scanf("%d %s %d %s",&q[i].a,oa,&q[i].b,ob); if(oa[0]=='A')va=0;else q[i].va=(oa[0]=='B')?2:4; if(ob[0]=='A')vb=0;else q[i].vb=(ob[0]=='B')?2:4; } int MS=1<<d; for(int i=0;i<MS;i++){ for(int j=1;j<=d;j++) s[wz[j]]='a'+((i>>j)&1); if(solve())return 0; } printf("-1"); } /* 5 2 acxax 10 2 B 1 A 3 C 4 C 4 B 3 C 5 B 3 B 2 B 3 A 3 A 2 A 5 B 1 C 3 B 1 B 2 C 4 C 4 B 2 A */
    Processed: 0.009, SQL: 8