首先我是的确确定了LRJ那个代码也是判断一个点的两种状态是否在一个连通分量内。
关于自己做的,自己又确定了一些,让自己那样先,比如说对于 3 6 1 AND这样3 6都已经确定的点,自己用Num记录的话结果死的很惨。
我也确定下,现场比赛自己创算法(指的是代码比较新)的话也许会死的很惨。。。
2-SAT,后来我忽然想到就是确定的位置也可以用这种对称方法做出来,就加一个每种状态都可以推出这种状态呗。。
顺便知道了RANK上排名超前的一般都加入了输入输出加速了
还顺便知道了OJ上的数据也许是随机出的
还顺便学习了下tarjan的2-SAT做法,其实思想本来就是类似的。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; //我的错误就是无法判断已经确定结果的边然后。。。。 const int maxn = 1500; int n,m; vector<int> G[maxn*3]; bool mark[maxn*3]; int s[maxn*3],c; char op[10]; bool dfs(int x) { if(mark[x^1]) return false;//这个一定是强连通分量果然 if(mark[x]) return true; mark[x]=true; s[c++]=x; for(int i=0;i<G[x].size();i++) if(!dfs(G[x][i])) return false; return true; } void init() { for(int i=0;i<n*2;i++) G[i].clear(); memset(mark,0,sizeof(mark)); } bool solve() { for(int i = 0;i < n*2; i += 2) { if( !mark[i] && !mark[i+1] ) { c = 0; if( !dfs(i) ) { while(c>0) mark[s[--c]]=false; if(!dfs(i+1)) return false; } } } return true; } int main() { int a,b,c; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=0;i<m;i++) { scanf("%d%d%d%s",&a,&b,&c,op); if(!strcmp(op,"AND")) { if(c==1) { G[a*2].push_back(b*2);//如果出现这种情况那么一定是真。就这样。 G[a*2+1].push_back(b*2); G[b*2].push_back(a*2); G[b*2+1].push_back(a*2); } else if(c==0) { G[a*2].push_back(b*2+1);//真只能放假 G[b*2].push_back(a*2+1); } } ////////// else if(!strcmp(op,"OR")) { if(c==1) { G[a*2+1].push_back(b*2);//a假b必须为真 G[b*2+1].push_back(a*2); } else if(c==0) { G[a*2].push_back(b*2+1); G[a*2+1].push_back(b*2+1);//必须都为0 G[b*2].push_back(a*2+1); G[b*2+1].push_back(a*2+1); } } //////////// else if(!strcmp("XOR",op)) { if(c==1) { G[a*2+1].push_back(b*2); G[a*2].push_back(b*2+1); G[b*2+1].push_back(a*2); G[b*2].push_back(a*2+1); } else if(c==0) { G[a*2+1].push_back(b*2+1); G[a*2].push_back(b*2); G[b*2+1].push_back(a*2+1); G[b*2].push_back(a*2); } } } if(solve()==false) printf("NO "); else { printf("YES "); } } return 0; }