2-sat

Posted cmyg

tags:

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

 

study from:

https://www.cnblogs.com/-ZZB-/p/6635483.html

 

条件1~条件n true 或 false (互反状态)

若干对  (not)条件x -> (not)条件y

 

https://www.luogu.org/problemnew/show/P4782

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <time.h>
  6 #include <string>
  7 #include <set>
  8 #include <map>
  9 #include <list>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <bitset>
 14 #include <ext/rope>
 15 #include <algorithm>
 16 #include <iostream>
 17 using namespace std;
 18 #define ll long long
 19 #define minv 1e-6
 20 #define inf 1e9
 21 #define pi 3.1415926536
 22 #define nl 2.7182818284
 23 const ll mod=1e9+7;//998244353
 24 const int maxn=2e6+10;
 25 
 26 vector<int>e[maxn];
 27 bool vis[maxn]={0},ins[maxn]={0};
 28 int num=0,g=0,_index=0;
 29 int dfn[maxn],low[maxn],st[maxn],tag[maxn];
 30 
 31 void tarjan(int d)
 32 {
 33     vector<int>::iterator i;
 34     int dd;
 35     dfn[d]=low[d]=++num;
 36     st[++g]=d;
 37     vis[d]=1;
 38     for (i=e[d].begin();i!=e[d].end();i++)
 39     {
 40         dd=*i;
 41         if (!vis[dd])
 42         {
 43             tarjan(dd);
 44             low[d]=min(low[d],low[dd]);
 45         }
 46         else if (!ins[dd])
 47             low[d]=min(low[d],dfn[dd]);
 48     }
 49     if (dfn[d]==low[d])
 50     {
 51         _index++;
 52         while (st[g]!=d)
 53         {
 54             tag[st[g]]=_index;
 55             ins[st[g]]=1;
 56             g--;
 57         }
 58         tag[st[g]]=_index;
 59         ins[st[g]]=1;
 60         g--;
 61     }
 62 }
 63 
 64 int main()
 65 {
 66     int n,m,a,b,i,j;
 67     scanf("%d%d",&n,&m);
 68     while (m--)
 69     {
 70         scanf("%d%d%d%d",&a,&i,&b,&j);
 71         if (i==1 && j==1)
 72         {
 73             e[a+n].push_back(b);
 74             e[b+n].push_back(a);
 75         }
 76         else if (i==1 && j==0)
 77         {
 78             e[a+n].push_back(b+n);
 79             e[b].push_back(a);
 80         }
 81         else if (i==0 && j==1)
 82         {
 83             e[a].push_back(b);
 84             e[b+n].push_back(a+n);
 85         }
 86         else
 87         {
 88             e[a].push_back(b+n);
 89             e[b].push_back(a+n);
 90         }
 91     }
 92     for (i=1;i<=(n<<1);i++)
 93         if (!vis[i])
 94             tarjan(i);
 95     for (i=1;i<=n;i++)
 96         if (tag[i]==tag[i+n])
 97         {
 98             printf("IMPOSSIBLE");
 99             return 0;
100         }
101     printf("POSSIBLE
");
102     for (i=1;i<=n;i++)
103     {
104         printf("%d",tag[i]<tag[i+n]);
105         if (i!=n)
106             printf(" ");
107     }
108     return 0;
109 }

 

技术分享图片

 

题目:

1.

http://poj.org/problem?id=3683

选择头部 与 选择尾部 为互反状态

两条线段:一条线段的a不能与另一条线段的b以一起,则a->反b , b->反a

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <time.h>
  6 #include <string>
  7 #include <set>
  8 #include <map>
  9 #include <list>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <bitset>
 14 #include <ext/rope>
 15 #include <algorithm>
 16 #include <iostream>
 17 using namespace std;
 18 #define ll long long
 19 #define minv 1e-6
 20 #define inf 1e9
 21 #define pi 3.1415926536
 22 #define nl 2.7182818284
 23 const ll mod=1e9+7;//998244353
 24 const int maxn=2e3+10;
 25 
 26 vector<int>e[maxn];
 27 bool vis[maxn]={0},ins[maxn]={0};
 28 int dfn[maxn],low[maxn],st[maxn],tag[maxn];
 29 int num=0,g=0,tot=0;
 30 int s[maxn],t[maxn],l[maxn];
 31 
 32 void tarjan(int d)
 33 {
 34     int dd;
 35     vector<int>::iterator i;
 36     vis[d]=1;
 37     dfn[d]=low[d]=++num;
 38     st[++g]=d;
 39     for (i=e[d].begin();i!=e[d].end();i++)
 40     {
 41         dd=*i;
 42         if (!vis[dd])
 43         {
 44             tarjan(dd);
 45             low[d]=min(low[d],low[dd]);
 46         }
 47         else if (!ins[dd])
 48             low[d]=min(low[d],dfn[dd]);
 49     }
 50     if (dfn[d]==low[d])
 51     {
 52         tot++;
 53         while (st[g]!=d)
 54         {
 55             tag[st[g]]=tot;
 56             ins[st[g]]=1;
 57             g--;
 58         }
 59         tag[st[g]]=tot;
 60         ins[st[g]]=1;
 61         g--;
 62     }
 63 }
 64 
 65 bool inter(int a,int b,int c,int d)
 66 {
 67     if (b<=c || d<=a)
 68         return 0;
 69     else
 70         return 1;
 71 }
 72 
 73 
 74 int main()
 75 {
 76     int n,i,j,s1,s2,t1,t2;
 77     scanf("%d",&n);
 78     for (i=1;i<=n;i++)
 79     {
 80         scanf("%d:%d %d:%d %d",&s1,&s2,&t1,&t2,&l[i]);
 81         s[i]=s1*60+s2;
 82         t[i]=t1*60+t2;
 83         if (t[i]-s[i]<l[i])
 84         {
 85             printf("NO
");
 86             return 0;
 87         }
 88     }
 89 
 90     for (i=1;i<=n;i++)
 91         for (j=i+1;j<=n;j++)
 92         {
 93             if (inter(s[i],s[i]+l[i],s[j],s[j]+l[j]))
 94             {
 95                 e[i].push_back(j+n);
 96                 e[j].push_back(i+n);
 97             }
 98             if (inter(s[i],s[i]+l[i],t[j]-l[j],t[j]))
 99             {
100                 e[i].push_back(j);
101                 e[j+n].push_back(i+n);
102             }
103             if (inter(t[i]-l[i],t[i],s[j],s[j]+l[j]))
104             {
105                 e[i+n].push_back(j+n);
106                 e[j].push_back(i);
107             }
108             if (inter(t[i]-l[i],t[i],t[j]-l[j],t[j]))
109             {
110                 e[i+n].push_back(j);
111                 e[j+n].push_back(i);
112             }
113         }
114     for (i=1;i<=(n<<1);i++)
115         if (!vis[i])
116             tarjan(i);
117     for (i=1;i<=n;i++)
118         if (tag[i]==tag[i+n])
119         {
120             printf("NO");
121             return 0;
122         }
123     printf("YES
");
124     for (i=1;i<=n;i++)
125     {
126         if (tag[i]<tag[i+n])
127             printf("%02d:%02d %02d:%02d
",s[i]/60,s[i]%60,(s[i]+l[i])/60,(s[i]+l[i])%60);
128         else
129             printf("%02d:%02d %02d:%02d
",(t[i]-l[i])/60,(t[i]-l[i])%60,t[i]/60,t[i]%60);
130     }
131     return 0;
132 }

 

 

2.

https://www.luogu.org/problemnew/show/P1776

a题选择1锦囊和a题选择2锦囊为互反状态

若a题和b题都选择1锦囊,则a题选择1锦囊->b题选择除1锦囊外的另外一个锦囊

 

3.

http://poj.org/problem?id=3678

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <time.h>
  6 #include <string>
  7 #include <set>
  8 #include <map>
  9 #include <list>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <bitset>
 14 #include <ext/rope>
 15 #include <algorithm>
 16 #include <iostream>
 17 using namespace std;
 18 #define ll long long
 19 #define minv 1e-6
 20 #define inf 1e9
 21 #define pi 3.1415926536
 22 #define nl 2.7182818284
 23 const ll mod=1e9+7;//998244353
 24 const int maxn=2e3+10;
 25 
 26 vector<int>e[maxn];
 27 bool vis[maxn]={0},ins[maxn]={0};
 28 int dfn[maxn],low[maxn],st[maxn],tag[maxn];
 29 int num=0,g=0,tot=0;
 30 
 31 void tarjan(int d)
 32 {
 33     int dd;
 34     vector<int>::iterator i;
 35     vis[d]=1;
 36     dfn[d]=low[d]=++num;
 37     st[++g]=d;
 38     for (i=e[d].begin();i!=e[d].end();i++)
 39     {
 40         dd=*i;
 41         if (!vis[dd])
 42         {
 43             tarjan(dd);
 44             low[d]=min(low[d],low[dd]);
 45         }
 46         else if (!ins[dd])
 47             low[d]=min(low[d],dfn[dd]);
 48     }
 49     if (dfn[d]==low[d])
 50     {
 51         tot++;
 52         while (st[g]!=d)
 53         {
 54             tag[st[g]]=tot;
 55             ins[st[g]]=1;
 56             g--;
 57         }
 58         tag[st[g]]=tot;
 59         ins[st[g]]=1;
 60         g--;
 61     }
 62 }
 63 
 64 bool inter(int a,int b,int c,int d)
 65 {
 66     if (b<=c || d<=a)
 67         return 0;
 68     else
 69         return 1;
 70 }
 71 
 72 
 73 int main()
 74 {
 75     int n,m,i,a,b,c;
 76     char d[5];
 77     scanf("%d%d",&n,&m);
 78     while (m--)
 79     {
 80         scanf("%d%d%d%s",&a,&b,&c,d);
 81         if (d[0]==A)
 82         {
 83             if (c==1)
 84             {
 85                 e[a].push_back(b);
 86                 e[b].push_back(a);
 87 
 88                 e[a+n].push_back(b);
 89                 e[a+n].push_back(b+n);
 90 
 91                 e[b+n].push_back(a);
 92                 e[b+n].push_back(a+n);
 93             }
 94             else
 95             {
 96                 e[a].push_back(b+n);
 97                 e[b].push_back(a+n);
 98             }
 99         }
100         else if (d[0]==O)
101         {
102             if (c==1)
103             {
104                 e[a+n].push_back(b);
105                 e[b+n].push_back(a);
106             }
107             else
108             {
109                 e[a+n].push_back(b+n);
110                 e[b+n].push_back(a+n);
111 
112                 e[a].push_back(b);
113                 e[a].push_back(b+n);
114 
115                 e[b].push_back(a);
116                 e[b].push_back(a+n);
117             }
118         }
119         else if (d[0]==X)
120         {
121             if (c==1)
122             {
123                 e[a].push_back(b+n);
124                 e[b].push_back(a+n);
125             }
126             else
127             {
128                 e[a].push_back(b);
129                 e[b].push_back(a);
130             }
131         }
132     }
133 
134     for (i=1;i<=(n<<1);i++)
135         if (!vis[i])
136             tarjan(i);
137     for (i=1;i<=n;i++)
138         if (tag[i]==tag[i+n])
139         {
140             printf("NO");
141             return 0;
142         }
143     printf("YES");
144     return 0;
145 }

 

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

模板 2-sat

POJ 3905 Perfect Election(2-sat)

BZOJ1823: [JSOI2010]满汉全席(2-sat)

[luogu4782]模板2-SAT 问题

POJ 2296 Map Labeler(2-sat)

BZOJ1823 [JSOI2010]满汉全席 2-sat