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,只是个人心得,错了请指出。。。

 

 

View Code
  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 }

posted on 2012-09-22 10:41  Wizmann  阅读(318)  评论(0编辑  收藏  举报

导航