2-Sat模板
Posted slrslr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2-Sat模板相关的知识,希望对你有一定的参考价值。
2-Sat
每种元素有两种状态,选或不选,有一些限制条件,这样的题目可以用2-sat解决。
4种模型:
1.(A,B)不能同时取
A->B‘,B->A‘
2.(A,B)不能同时不取
A‘->B,B‘->A
3.(A,B)要么都取,要么都不取
A→B,B→A,A‘→B‘,B‘→A‘
4.(A,B)两者必取A
A‘->A
对于第四个,我的理解是,无论如何A‘是无法被选中的,因为选A‘必选A这个限制是不符合规则的,所以这样A‘一定不会被选上,A也就一定会被选上。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 2000010 6 using namespace std; 7 struct point{ 8 int to,next; 9 }e[M<<2]; 10 int n,m,num,tot,cnt,top; 11 int head[M],dfn[M],st[M],low[M],co[M]; 12 bool vis[M]; 13 void add(int from,int to) 14 { 15 e[++num].next=head[from]; 16 e[num].to=to; 17 head[from]=num; 18 } 19 void tarjan(int x) 20 { 21 dfn[x]=low[x]=++cnt; 22 st[++top]=x; 23 vis[x]=true; 24 for(int i=head[x];i;i=e[i].next) 25 { 26 int to=e[i].to; 27 if(!dfn[to]) 28 { 29 tarjan(to); 30 low[x]=min(low[x],low[to]); 31 } 32 else if(vis[to]) low[x]=min(low[x],dfn[to]); 33 } 34 if(low[x]==dfn[x]) 35 { 36 tot++; 37 while(st[top+1]!=x) 38 { 39 co[st[top]]=tot; 40 vis[st[top]]=false; 41 top--; 42 } 43 } 44 } 45 bool two_sat() 46 { 47 for(int i=1;i<=2*n;i++) 48 if(!dfn[i]) 49 tarjan(i); 50 for(int i=1;i<=n;i++) 51 if(co[i]==co[i+n]) 52 return false; 53 return true; 54 } 55 int main() 56 { 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=m;i++) 59 { 60 int a,b,ba,bb; 61 scanf("%d%d%d%d",&a,&ba,&b,&bb); 62 int A=a+ba*n; 63 int BB=b+(bb^1)*n; 64 int B=b+bb*n; 65 int AA=a+(ba^1)*n; 66 add(BB,A); add(AA,B); 67 } 68 if(two_sat()) 69 { 70 printf("POSSIBLE "); 71 for(int i=1;i<=n;i++) 72 printf("%d ",co[i]>co[i+n]); 73 } 74 else printf("IMPOSSIBLE"); 75 return 0; 76 }
以上是关于2-Sat模板的主要内容,如果未能解决你的问题,请参考以下文章