1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 10010*6; 5 const int MAXM = 20*10010; 6 const int WE = 6; 7 8 struct TwoSAT{ 9 int n, ecnt, dfs_clock, scc_cnt; 10 int St[MAXN], c; 11 int head[MAXN], sccno[MAXN], pre[MAXN], lowlink[MAXN]; 12 int next[MAXM], to[MAXM]; 13 14 void init(int nn){ 15 n = nn; 16 ecnt = 2; dfs_clock = scc_cnt = 0; 17 memset(head,0,sizeof(head)); 18 memset(sccno,0,sizeof(sccno)); 19 memset(pre,0,sizeof(pre)); 20 } 21 22 void addEdge(int x, int y){ 23 to[ecnt] = y; next[ecnt] = head[x]; head[x] = ecnt++; 24 //printf("%d->%d\n",x,y); 25 } 26 27 void addEdge2(int x, int y){ 28 addEdge(x,y); addEdge(y,x); 29 } 30 31 void dfs(int u){ 32 lowlink[u] = pre[u] = ++dfs_clock; 33 St[++c] = u; 34 for(int p = head[u]; p; p = next[p]){ 35 int &v = to[p]; 36 if(!pre[v]){ 37 dfs(v); 38 if(lowlink[u] > lowlink[v]) lowlink[u] = lowlink[v]; 39 }else if(!sccno[v]){ 40 if(lowlink[u] > pre[v]) lowlink[u] = pre[v]; 41 } 42 } 43 if(lowlink[u] == pre[u]){ 44 ++scc_cnt; 45 while(true){ 46 int x = St[c--]; 47 sccno[x] = scc_cnt; 48 if(x == u) break; 49 } 50 } 51 } 52 53 bool solve(){ 54 for(int i = 0; i < n; ++i) 55 if(!pre[i]) dfs(i); 56 for(int i = 0; i < n; i += 2) 57 if(sccno[i] == sccno[i^1]) return false; 58 return true; 59 } 60 61 void test(){ 62 for(int i = 0; i < n; ++i){ 63 printf("%d\n",i+1); 64 for(int p = head[i]; p; p = next[p]) printf("%d ", to[p]+1); 65 } 66 } 67 68 } G; 69 70 int B[MAXN]; 71 72 int main(){ 73 int T, n, m, a, b, k; 74 scanf("%d", &T); 75 for(int t = 1; t <= T; ++t){ 76 scanf("%d%d",&n,&m); 77 G.init(n*WE); 78 for(int i = 0; i < n; ++i){ 79 scanf("%d", &b); 80 if(b == 1) { 81 //G.addEdge(i*WE+2*2, i*WE+2*2+1); 82 G.addEdge(i*WE+1*2+1, i*WE+0*2); 83 G.addEdge(i*WE+0*2+1, i*WE+1*2); 84 } 85 if(b == 2) { 86 //G.addEdge(i*WE+0*2, i*WE+0*2+1); 87 G.addEdge(i*WE+1*2+1, i*WE+2*2); 88 G.addEdge(i*WE+2*2+1, i*WE+1*2); 89 } 90 if(b == 3) { 91 //G.addEdge(i*WE+1*2, i*WE+1*2+1); 92 G.addEdge(i*WE+0*2+1, i*WE+2*2); 93 G.addEdge(i*WE+2*2+1, i*WE+0*2); 94 } 95 } 96 while(m--){ 97 scanf("%d%d%d", &a, &b, &k); 98 --a, --b; 99 if(k == 0){ 100 for(int i = 0; i < 3; ++i) { 101 G.addEdge2(a*WE+i*2, b*WE+i*2); 102 G.addEdge2(a*WE+i*2+1, b*WE+i*2+1); 103 } 104 }else{ 105 for(int i = 0; i < 3; ++i){ 106 G.addEdge(a*WE+i*2, b*WE+i*2+1); 107 G.addEdge(b*WE+i*2, a*WE+i*2+1); 108 } 109 } 110 } 111 for(int i = 0; i < n; ++i) 112 for(int j = 0; j < 3; ++j) 113 for(int k = 0; k < 3; ++k) if(j != k){ 114 G.addEdge(i*WE+j*2, i*WE+k*2+1); 115 } 116 if(G.solve()) printf("Case #%d: yes\n", t); 117 else printf("Case #%d: no\n", t); 118 } 119 return 0; 120 }
思路2:2-SAT问题,首先别人出布,你肯定不能出石头,那么你只能在剩下的两个之中选一个,那么 剪刀 xor 布 = true且石头=false;若A、B不能出一样的,比如那么对于剪刀来讲,A出了剪刀,B就不能出剪刀,B出了剪刀,A就不能出剪刀;A、B要一样也类似。
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 10010*6; 5 const int MAXM = 20*10010; 6 const int WE = 6; 7 8 struct TwoSAT{ 9 int n, ecnt, dfs_clock, scc_cnt; 10 int St[MAXN], c; 11 int head[MAXN], sccno[MAXN], pre[MAXN], lowlink[MAXN]; 12 int next[MAXM], to[MAXM]; 13 14 void init(int nn){ 15 n = nn; 16 ecnt = 2; dfs_clock = scc_cnt = 0; 17 memset(head,0,sizeof(head)); 18 memset(sccno,0,sizeof(sccno)); 19 memset(pre,0,sizeof(pre)); 20 } 21 22 void addEdge(int x, int y){ 23 to[ecnt] = y; next[ecnt] = head[x]; head[x] = ecnt++; 24 //printf("%d->%d\n",x,y); 25 } 26 27 void addEdge2(int x, int y){ 28 addEdge(x,y); addEdge(y,x); 29 } 30 31 void dfs(int u){ 32 lowlink[u] = pre[u] = ++dfs_clock; 33 St[++c] = u; 34 for(int p = head[u]; p; p = next[p]){ 35 int &v = to[p]; 36 if(!pre[v]){ 37 dfs(v); 38 if(lowlink[u] > lowlink[v]) lowlink[u] = lowlink[v]; 39 }else if(!sccno[v]){ 40 if(lowlink[u] > pre[v]) lowlink[u] = pre[v]; 41 } 42 } 43 if(lowlink[u] == pre[u]){ 44 ++scc_cnt; 45 while(true){ 46 int x = St[c--]; 47 sccno[x] = scc_cnt; 48 if(x == u) break; 49 } 50 } 51 } 52 53 bool solve(){ 54 int i; 55 for(i = 0; i < n; ++i) 56 if(!pre[i]) dfs(i); 57 for(i = 0; i < n; i += 2) 58 if(sccno[i] == sccno[i^1]) return false; 59 return true; 60 } 61 62 void test(){ 63 for(int i = 0; i < n; ++i){ 64 printf("%d\n",i+1); 65 for(int p = head[i]; p; p = next[p]) printf("%d ", to[p]+1); 66 } 67 } 68 69 } G; 70 71 int B[MAXN]; 72 73 int main(){ 74 int T, n, m, a, b, k; 75 scanf("%d", &T); 76 for(int t = 1; t <= T; ++t){ 77 scanf("%d%d",&n,&m); 78 G.init(n*WE); 79 for(int i = 0; i < n; ++i){ 80 scanf("%d", &b); 81 if(b == 1) { 82 G.addEdge(i*WE+2*2, i*WE+2*2+1); 83 G.addEdge2(i*WE+1*2+1, i*WE+0*2); 84 G.addEdge2(i*WE+1*2, i*WE+0*2+1); 85 } 86 if(b == 2) { 87 G.addEdge(i*WE+0*2, i*WE+0*2+1); 88 G.addEdge2(i*WE+1*2+1, i*WE+2*2); 89 G.addEdge2(i*WE+1*2, i*WE+2*2+1); 90 } 91 if(b == 3) { 92 G.addEdge(i*WE+1*2, i*WE+1*2+1); 93 G.addEdge2(i*WE+0*2+1, i*WE+2*2); 94 G.addEdge2(i*WE+0*2, i*WE+2*2+1); 95 } 96 } 97 while(m--){ 98 scanf("%d%d%d", &a, &b, &k); 99 --a, --b; 100 if(k == 0){ 101 for(int i = 0; i < 3; ++i) { 102 G.addEdge2(a*WE+i*2, b*WE+i*2); 103 G.addEdge2(a*WE+i*2+1, b*WE+i*2+1); 104 } 105 }else{ 106 for(int i = 0; i < 3; ++i){ 107 G.addEdge(a*WE+i*2, b*WE+i*2+1); 108 G.addEdge(b*WE+i*2, a*WE+i*2+1); 109 } 110 } 111 } 112 if(G.solve()) printf("Case #%d: yes\n", t); 113 else printf("Case #%d: no\n", t); 114 } 115 return 0; 116 }
思路3:实际上还有时空复杂度都比较好的方法,就是每个ROUND都不要必败的点,网上有很多都是这个思路的,不过写起来比较麻烦我就不写啦~~