LOJ#2305. 「NOI2017」游戏 枚举+2-SAT
调都没调就 1 A 了,开心.
一些细节:
1. 当 3 个点中强制一个点不选时,又有 (hi,hj) 这种限制时直接跳过即可.
2. 当有 (h_{i},h_{j}) 且 i 这个位置存在,但是 j 不存在的时候显然是不可以选择 i 的,那就直接让 i 连 i' 就行.
3. 2-SAT 的建图始终是有对称性的,即 a->b 就要有 b'->a',这个一定注意.
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #include <bits/stdc++.h> #define N 100009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; char str[N]; stack< int >sta; int n,D,S,m,edges,scc,tim,tot; int vis[N],mark[N],bu[N],ID[2][N],ge[N][4]; int hd[N],to[N<<1],nex[N<<1],dfn[N],low[N],idx[N]; struct data { int i,hi,j,hj; }h[N]; void add( int u, int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void tarjan( int x) { sta.push(x),low[x]=dfn[x]=++tim; for ( int i=hd[x];i;i=nex[i]) { int y=to[i]; if (!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if (!idx[y]) low[x]=min(low[x],dfn[y]); } if (low[x]==dfn[x]) { ++scc; for (;;) { int u=sta.top(); sta.pop(); idx[u]=scc; if (u==x) break ; } } } void clr() { for ( int i=1;i<=tot;++i) hd[i]=dfn[i]=low[i]=idx[i]=0; for ( int i=0;i<=edges;++i) nex[i]=to[i]=0; } int calc() { int x,y,z; for ( int i=1;i<=n;++i) { if (vis[i]) { if (mark[i]==0) str[i]= 'a' ; if (mark[i]==1) str[i]= 'b' ; } if (str[i]== 'a' ) ge[i][1]=0,ge[i][2]=1; if (str[i]== 'b' ) ge[i][0]=0,ge[i][2]=1; if (str[i]== 'c' ) ge[i][0]=0,ge[i][1]=1; } for ( int i=1;i<=m;++i) { data e=h[i]; // 反正肯定不会选 if (str[e.i]== 'a' +e.hi) continue ; // 当前肯定不能选 if (str[e.j]== 'a' +e.hj) { add(ID[ge[e.i][e.hi]][e.i],ID[ge[e.i][e.hi]^1][e.i]); continue ; } // i->j, j'->i' add(ID[ge[e.i][e.hi]][e.i],ID[ge[e.j][e.hj]][e.j]); add(ID[ge[e.j][e.hj]^1][e.j],ID[ge[e.i][e.hi]^1][e.i]); } for ( int i=1;i<=tot;++i) if (!dfn[i]) tarjan(i); int flag=1; for ( int i=1;i<=n;++i) if (idx[ID[0][i]]==idx[ID[1][i]]) flag=0; if (flag) { for ( int i=1;i<=n;++i) { x=ID[0][i],y=ID[1][i]; if (str[i]== 'a' ) printf ( "%c" ,idx[x]<idx[y]? 'B' : 'C' ); if (str[i]== 'b' ) printf ( "%c" ,idx[x]<idx[y]? 'A' : 'C' ); if (str[i]== 'c' ) printf ( "%c" ,idx[x]<idx[y]? 'A' : 'B' ); } } clr(); return flag; } int main() { // setIO("input"); int x,y,z; char a[2],b[2]; scanf ( "%d%d%s%d" ,&n,&x,str+1,&m); for ( int i=1;i<=m;++i) { scanf ( "%d%s%d%s" ,&h[i].i,a,&h[i].j,b); h[i].hi=a[0]- 'A' ,h[i].hj=b[0]- 'A' ; } for ( int i=1;i<=n;++i) if (str[i]== 'x' ) vis[i]=1,bu[++D]=i; for ( int i=1;i<=n;++i) ID[0][i]=++tot; for ( int i=1;i<=n;++i) ID[1][i]=++tot; // 0 表示 不选 A // 1 表示 不选 B for ( int i=0;i<(1<<D);++i) { for ( int j=0;j<D;++j) { if (i&(1<<j)) mark[bu[j+1]]=1; else mark[bu[j+1]]=0; } if (calc()) return 0; } if (!D&&calc()) return 0; printf ( "-1" ); return 0; } |
标签:
2-SAT
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· 终于决定:把自己家的能源管理系统开源了!
· [.NET] 使用客户端缓存提高API性能
· 外部H5唤起常用小程序链接规则整理
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· WPF 怎么利用behavior优雅的给一个Datagrid添加一个全选的功能
2019-06-09 BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组 + 贪心 + 细节
2019-06-09 BZOJ 1692: [Usaco2007 Dec]队列变换 后缀数组 + 贪心
2019-06-09 luogu P2852 [USACO06DEC]牛奶模式Milk Patterns 后缀数组 + Height数组 + 二分答案 + 扫描
2019-06-09 BZOJ2251 [2010Beijing Wc]外星联络 后缀数组 + Height数组
2019-06-09 [NOI2015]软件包管理器 树链剖分 + 线段树