两个人玩剪刀石头布,他们玩了n把,给了你A这n把都出了什么,问你B能否会赢,其中A会限制B某些局数出的要相同,某些局数出的要不同,只要B满足他的限制,并且没没有输掉任何一把就算赢(没有输掉就是平或者赢)。
思路:
首先考虑下,对于每一步,我们知道A出了什么,那么也就知道B在这不可以出什么,比如A在这一步出了1 那么B可以出1,2。对于每一步B都有两种选择,并且在步于步之间有一些限制,两种选择,一些限制,显然2sat,把每一次可以出的两个看成一组,一个是a,一个是~a,对于每一种限制我们只要找出它的矛盾对就行了,矛盾对的建边遵循 x ,y矛盾则有add(x ,~y) ,add(y ,~x) ,要注意这里面的 x,~x是相对而言,x = ~x^1 同时 x^1 = ~x,建边的时候别糊涂就行了,总之这个题目应该是2算是sat的简单题目。
#include<stdio.h> #include<string.h> #include<stack> #define N_node 20000 + 100 #define N_edge 50000 + 500 using namespace std; typedef struct { int to ,next; }STAR; STAR E1[N_edge] ,E2[N_edge]; int list1[N_node] ,list2[N_node] ,tot; int Belong[N_node] ,cnt; int mark[N_node]; int A[11000][2]; stack<int>st; void add(int a ,int b) { E1[++tot].to = b; E1[tot].next = list1[a]; list1[a] = tot; E2[tot].to = a; E2[tot].next = list2[b]; list2[b] = tot; } void DFS1(int s) { mark[s] = 1; for(int k = list1[s] ;k ;k = E1[k].next) if(!mark[E1[k].to])DFS1(E1[k].to); st.push(s); } void DFS2(int s) { mark[s] = 1 ,Belong[s] = cnt; for(int k = list2[s] ;k ;k = E2[k].next) if(!mark[E2[k].to])DFS2(E2[k].to); } bool ok(int n) { memset(mark ,0 ,sizeof(mark)); while(!st.empty()) st.pop(); for(int i = 0 ;i < n * 2 ;i ++) if(!mark[i]) DFS1(i); memset(mark ,0 ,sizeof(mark)); cnt = 0; while(!st.empty()) { int xin = st.top(); st.pop(); if(mark[xin]) continue; cnt ++; DFS2(xin); } int mk = 0; for(int i = 0 ;i < n * 2 && !mk ;i += 2) if(Belong[i] == Belong[i^1]) mk = 1; return !mk; } int main () { int t ,n ,m ,i ,a ,b ,c ,cas = 1; scanf("%d" ,&t); while(t--) { scanf("%d %d" ,&n ,&m); for(i = 1 ;i <= n ;i ++) { scanf("%d" ,&a); A[i][0] = a; A[i][1] = a % 3 + 1; } memset(list1 ,0 ,sizeof(list1)); memset(list2 ,0 ,sizeof(list2)); tot = 1; for(i = 1 ;i <= m ;i ++) { scanf("%d %d %d" ,&a ,&b ,&c); int x1 = a * 2 ,x2 = a * 2 + 1; int y1 = b * 2 ,y2 = b * 2 + 1; if(!c && A[a][0] != A[b][0] || c && A[a][0] == A[b][0]) add(x1 ,y1^1) ,add(y1 ,x1^1); if(!c && A[a][0] != A[b][1] || c && A[a][0] == A[b][1]) add(x1 ,y2^1) ,add(y2 ,x1^1); if(!c && A[a][1] != A[b][0] || c && A[a][1] == A[b][0]) add(x2 ,y1^1) ,add(y1 ,x2^1); if(!c && A[a][1] != A[b][1] || c && A[a][1] == A[b][1]) add(x2 ,y2^1) ,add(y2 ,x2^1); } printf("Case #%d: " ,cas ++); if(!ok(n)) puts("no"); else puts("yes"); } return 0; }