1 2 0 1 2 0 1 1 2 2 4 0 1 2 3 4 5 0 3 0 4 1 3 1 4
yes no
2-SAT水题
为什么要用反边存缩点后的图?
考虑到算法传递标记的时候,“选择”标记是没有进行传递的,也就是说正向边是没有利用到的,传递的都是“不选择”标记,也就是说走
的都是反边。
//#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXN = 1e6+7; struct node { int v,next; }edge[MAXN]; int head[MAXN],index; void add_edge(int u,int v) { edge[index].v=v; edge[index].next=head[u]; head[u]=index++; } int DFN[MAXN],low[MAXN],stack_[MAXN],in_stack[MAXN],belong[MAXN]; int cir,top,temp; void Tarjan(int u) { int p; DFN[u]=low[u]=++temp; in_stack[u]=1; stack_[top++]=u; for(int i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(!DFN[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(in_stack[v]) { low[u]=min(low[u],DFN[v]); } } if(low[u]==DFN[u]) { ++cir; do{ p=stack_[--top]; in_stack[p]=0; belong[p]=cir; }while(p!=u); } } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { int a,b,c; temp=cir=top=index=0; memset(DFN,0,sizeof(DFN)); memset(head,-1,sizeof(head)); memset(in_stack,0,sizeof(in_stack)); for(int i=0; i<n; ++i) { scanf("%d%d%d",&a,&b,&c); add_edge((a<<1)^1,b<<1); add_edge((a<<1)^1,c<<1); add_edge((b<<1)^1,a<<1); add_edge((c<<1)^1,a<<1); } for(int i=0; i<m; ++i) { scanf("%d%d",&a,&b); add_edge(a<<1,(b<<1)^1); add_edge(b<<1,(a<<1)^1); } for(int i=0; i<n*6; ++i) if(!DFN[i]) Tarjan(i); int flag=0; for(int i=0; i<n*3; ++i) { if(belong[i<<1]==belong[(i<<1)^1]) {flag=1;break;} } if(flag)printf("no\n"); else printf("yes\n"); } return 0; }