HDU 3715 2-SAT入门
2-SAT是一种神奇的算法问题。
具体是什么我也不想细说,因为细说不了。。。
只是讨论一下建图。
2-SAT存在两种关系,互斥与共生。
比如此题,对于x[i],不能既为0,又为1。这就是一种互斥关系。
又由于如果c[i]==0,则x[a[i]]为0的话,x[b[i]]必为1,这就是共生关系。
解决2-SAT问题的方法就是将共生关系连边,然后求出强连通分量。再用互斥关系寻找是否矛盾。
这个其实很好理解,如果两个互斥条件共生,必然是一个错误解。
到现在我才做过两道2-SAT,只是个人心得,错了请指出。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //Result:2012-09-22 10:23:11 Accepted 3715 671MS 1104K 2221 B G++ Wizmann 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 10 using namespace std; 11 12 #define print(x) cout<<x<<endl 13 #define input(x) cin>>x 14 #define N 512 15 #define M 40000 16 #define SIZE 10240 17 18 struct node 19 { 20 int val,next; 21 node(){} 22 node(int ival,int inext) 23 { 24 val=ival;next=inext; 25 } 26 }; 27 28 int n,m; 29 int a[SIZE],b[SIZE],c[SIZE]; 30 31 32 int head[SIZE]; 33 node g[M]; 34 int ind; 35 36 char instack[SIZE]; 37 stack<int> st; 38 int dfn[SIZE],scc[SIZE],num[SIZE],low[SIZE]; 39 int sccnr,nr; 40 41 void init() 42 { 43 ind=0; 44 memset(head,-1,sizeof(head)); 45 memset(instack,0,sizeof(instack)); 46 memset(scc,0,sizeof(scc)); 47 memset(num,0,sizeof(num)); 48 memset(low,0,sizeof(low)); 49 memset(dfn,0,sizeof(dfn)); 50 st=stack<int>(); 51 nr=1;sccnr=0; 52 } 53 54 void tarjan(int pos) 55 { 56 low[pos]=dfn[pos]=nr++; 57 st.push(pos); 58 instack[pos]=1; 59 60 for(int i=head[pos];i!=-1;i=g[i].next) 61 { 62 int j=g[i].val; 63 if(!dfn[j]) 64 { 65 tarjan(j); 66 low[pos]=min(low[pos],low[j]); 67 } 68 else if(instack[j]) 69 { 70 low[pos]=min(low[pos],dfn[j]); 71 } 72 } 73 74 if(dfn[pos]==low[pos]) 75 { 76 sccnr++; 77 while(1) 78 { 79 int t=st.top(); 80 instack[t]=0; 81 st.pop(); 82 scc[t]=sccnr; 83 num[sccnr]++; 84 if(t==pos) break; 85 } 86 } 87 } 88 89 90 bool zSat() 91 { 92 for(int i=0;i<n*2;i++) 93 { 94 if(!dfn[i]) tarjan(i); 95 } 96 for(int i=0;i<n;i++) 97 { 98 if(scc[i]==scc[i+n]) 99 { 100 return false; 101 } 102 } 103 return true; 104 } 105 106 107 108 void addEdge(int a,int b) 109 { 110 g[ind]=node(b,head[a]); 111 head[a]=ind++; 112 } 113 114 115 void makeG(int x) 116 { 117 init(); 118 for(int i=0;i<x;i++) 119 { 120 int p=a[i],q=b[i]; 121 if(c[i]==0) 122 { 123 addEdge(p,q+n); 124 addEdge(q,p+n); 125 } 126 else if(c[i]==1) 127 { 128 addEdge(p,q); 129 addEdge(q,p); 130 addEdge(p+n,q+n); 131 addEdge(q+n,p+n); 132 } 133 else if(c[i]==2) 134 { 135 addEdge(p+n,q); 136 addEdge(q+n,p); 137 } 138 } 139 } 140 141 int slove() 142 { 143 int l=0,r=m; 144 while(l<=r) 145 { 146 int mid=(l+r)>>1; 147 makeG(mid); 148 if(zSat()) l=mid+1; 149 else r=mid-1; 150 } 151 return r; 152 } 153 154 int main() 155 { 156 int T; 157 input(T); 158 while(T--) 159 { 160 input(n>>m); 161 for(int i=0;i<m;i++) 162 { 163 scanf("%d%d%d",a+i,b+i,c+i); 164 } 165 print(slove()); 166 } 167 return 0; 168 }