poj 3678(SCC+2-SAT)
https://www.cnblogs.com/violet-acmer/p/9769406.html
难点:
题意理解+构图
题意:
有n个点 v[0,2......,n-1](v[i]值为0或1),边(a[i],b[i])间的权值为c[i],现在给出它们之间的一些逻辑运算的结果(比如c[1]=a[1] & b[1] = 1),逻辑运算有AND OR XOR三种,问是否存在一种满足所有条件的取值方案。
构图难点:
如果类似 u v 1 AND这样的数据,说明u,v的1必须都选,那么就把u的0连向u的1,v的0连向v的1,这样的目的是使得推出矛盾;
同理 u v 0 or 这样的数据,说明u,v的0必须都选,那么就把u的1连向u的0,v的1连向v的0,这样的目的是使得推出矛盾;
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 using namespace std; 6 #define pb push_back 7 #define mem(a,b) (memset(a,b,sizeof a)) 8 const int maxV=1e3+50; 9 const int maxE=1e6+50; 10 11 int n,m; 12 int a[maxE],b[maxE],c[maxE]; 13 char op[4]; 14 int scc[2*maxV]; 15 bool vis[2*maxV]; 16 vector<int >vs; 17 vector<int >G[2*maxV],rG[2*maxV]; 18 void addEdge(int u,int v) 19 { 20 G[u].pb(v); 21 rG[v].pb(u); 22 } 23 void Dfs(int u) 24 { 25 vis[u]=true; 26 for(int i=0;i < G[u].size();++i) 27 { 28 int to=G[u][i]; 29 if(!vis[to]) 30 Dfs(to); 31 } 32 vs.pb(u); 33 } 34 void rDfs(int u,int k) 35 { 36 vis[u]=true; 37 scc[u]=k; 38 for(int i=0;i < rG[u].size();++i) 39 { 40 int to=rG[u][i]; 41 if(!vis[to]) 42 rDfs(to,k); 43 } 44 } 45 void SCC() 46 { 47 mem(vis,false); 48 vs.clear(); 49 for(int i=0;i < 2*n;++i) 50 if(!vis[i]) 51 Dfs(i); 52 mem(vis,false); 53 int k=0; 54 for(int i=vs.size()-1;i >= 0;--i) 55 { 56 int to=vs[i]; 57 if(!vis[to]) 58 rDfs(to,++k); 59 } 60 } 61 void Init() 62 { 63 for(int i=0;i < maxV;++i) 64 G[i].clear(),rG[i].clear(); 65 } 66 int main() 67 { 68 scanf("%d%d",&n,&m); 69 Init(); 70 for(int i=1;i <= m;++i) 71 { 72 scanf("%d%d%d%s",a+i,b+i,c+i,op); 73 switch (op[0]) 74 { 75 case 'A': 76 if(c[i] == 0) 77 addEdge(a[i],b[i]+n),addEdge(b[i],a[i]+n); 78 else 79 addEdge(a[i]+n,a[i]),addEdge(b[i]+n,b[i]); 80 break; 81 case 'O': 82 if(c[i] == 1) 83 addEdge(a[i]+n,b[i]),addEdge(b[i]+n,a[i]); 84 else 85 addEdge(a[i],a[i]+n),addEdge(b[i],b[i]+n); 86 break; 87 case 'X': 88 if(c[i] == 1) 89 { 90 addEdge(a[i],b[i]+n),addEdge(b[i]+n,a[i]); 91 addEdge(a[i]+n,b[i]),addEdge(b[i],a[i]+n); 92 } 93 else 94 { 95 addEdge(a[i],b[i]),addEdge(b[i],a[i]); 96 addEdge(a[i]+n,b[i]+n),addEdge(b[i]+n,a[i]+n); 97 } 98 break; 99 } 100 } 101 SCC(); 102 bool flag=false; 103 for(int i=0;i < n;++i) 104 if(scc[i] == scc[i+n]) 105 flag=true; 106 if(flag) 107 printf("NO\n"); 108 else 109 printf("YES\n"); 110 111 }