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 }

你可能感兴趣的:(HDU)