模板 2-sat

Posted xiaobuxie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板 2-sat相关的知识,希望对你有一定的参考价值。

  1 //https://blog.csdn.net/jarjingx/article/details/8521690
  2 //上面是讲解,下面是代码
  3 //https://www.e-learn.cn/content/qita/1061337
  4 //poj3648
  5 //女2n男2n+1
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cstring>
  9 #include<queue>
 10 using namespace std;
 11 const int N=1e5+6;
 12 struct edge
 13     int to,nex;
 14 e[N];
 15 edge e2[N];
 16 int h[N],h2[N],sta[N],col[N],blg[N],low[N],dfn[N],in[N],ops[N];
 17 bool insta[N];
 18 int n,m,cnt,cnt2,dfsnum,top;
 19 void add(int a,int b)
 20     e[++cnt]=(edge)b,h[a];
 21     h[a]=cnt;
 22 
 23 void add2(int a,int b)
 24     e2[++cnt2]=(edge)b,h2[a];
 25     h2[a]=cnt2;
 26 
 27 void tarjan(int x)
 28     low[x]=dfn[x]=++dfsnum;
 29     insta[x]=1;
 30     sta[++top]=x;
 31     for(int i=h[x];i;i=e[i].nex)
 32         int v=e[i].to;
 33         if(!dfn[v])
 34             tarjan(v);
 35             low[x]=min(low[x],low[v]);
 36         
 37         else if(insta[v]) low[x]=min(low[x],dfn[v]);
 38     
 39     int cur;
 40     if(dfn[x]==low[x])
 41         ++blg[0];
 42         do
 43             cur=sta[top--];
 44             insta[cur]=0;
 45             blg[cur]=blg[0];
 46         while(cur!=x);
 47     
 48 
 49 int main()
 50     while(~scanf("%d%d",&n,&m))
 51         //读入建图
 52         cnt=1;dfsnum=0;top=0,cnt2=1;
 53         memset(col,0,sizeof(col));
 54         memset(h,0,sizeof(h));
 55         memset(h2,0,sizeof(h2));
 56         memset(insta,0,sizeof(insta));
 57         memset(dfn,0,sizeof(dfn));
 58         memset(in,0,sizeof(in));
 59         if(n==0 && m==0) break;
 60         for(int i=1;i<=m;++i)
 61             int a,b;char c,d;
 62             scanf("%d%c %d%c",&a,&c,&b,&d);
 63             if(c==h && d==h)
 64                 add(2*a+1,2*b);
 65                 add(2*b+1,2*a);
 66             
 67             if(c==h && d==w)
 68                 add(2*a+1,2*b+1);
 69                 add(2*b,2*a);
 70             
 71             if(c==w && d==h)
 72                 add(2*a,2*b);
 73                 add(2*b+1,2*a+1);
 74             
 75             if(c==w && d==w)
 76                 add(2*a,2*b+1);
 77                 add(2*b,2*a+1);
 78             
 79         
 80         add(0,1);
 81         //缩点
 82         for(int i=0; i < 2*n; ++i)
 83             if(!dfn[i]) tarjan(i);
 84         
 85         bool fg=1;
 86         for(int i=0;i<2*n;i+=2)
 87             if(blg[i]==blg[i^1])
 88                 puts("bad luck");
 89                 fg=0;
 90                 break;
 91             
 92         
 93         if(!fg) continue;
 94         //建反向图
 95         for(int u=0;u<2*n;++u)
 96             for(int i=h[u];i;i=e[i].nex)
 97                 int v=e[i].to;
 98                 int t1=blg[u],t2=blg[v];
 99                 if(t1!=t2)
100                     add2(t2,t1);
101                     ++in[t1];
102                 
103             
104         
105         for(int i=0;i<2*n;i+=2)
106             ops[blg[i]]=blg[i^1];
107             ops[blg[i^1]]=blg[i];
108         
109         //拓扑(染色)
110         queue<int> q;
111         for(int i=1;i<=blg[0];++i)
112             if(!in[i]) q.push(i);
113         
114         while(!q.empty())
115             int u=q.front();
116             q.pop();
117             if(!col[u])
118                 col[u]=1;
119                 col[ops[u]]=-1;
120             
121             for(int i=h2[u];i;i=e2[i].nex)
122                 int v=e2[i].to;
123                 --in[v];
124                 if(!in[v]) q.push(v);
125             
126         
127         //输出
128         for(int i=1;i<n; ++i)
129             if(col[blg[i<<1]]==-1) printf("%dw",i);
130             else printf("%dh",i);
131             if(i<n-1) printf(" ");
132             else printf("\n");
133         
134     
135     return 0;
136 

 

以上是关于模板 2-sat的主要内容,如果未能解决你的问题,请参考以下文章

[蒟蒻修炼计划][模板] 2-SAT

[模板]2-SAT 问题

2-sat模板

模板 2-sat

2-Sat模板

模板2-sat