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的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3905 Perfect Election(2-sat)