I will not talk much about the two SAT papers, "Solving 2-SAT problems by symmetry" (Wu Zhe's WC paper) and "2-SAT Solution Analysis" (Zhao Shuang, wu's paper illustrates the 2-SAT graph creation method by examples, while Zhao Shuang's paper focuses on theory. First, for creating a graph, if there is a conflict between a and B, then a and B will be connected to an edge, but not if B is selected after a is selected, then the edge AB will be selected, it seems that there is no difference, but it will actually cause errors. When I first wrote 2-SAT, it was because the 1.1 was written incorrectly, and then I figured it out.
I have been wondering why it is not a positive graph because of the necessary conditions and I have not thought clearly about the part of the output answer, the topological sorting and the building of an inverse graph, I will try again later.
POJ 2723
This question was just written:
There are 2 * n keys that are divided into n groups. If one key is selected for each group, the other key disappears. There are m doors, and there are two locks on each door. As long as one lock is opened, the door can be opened. To open the I + 1 door, you must first open the I door. Ask the maximum number of opened doors.
First, consider that if you can open the x + 1 door, you can open the I door. The next step is verification.
2-The SAT graph creation method is as follows:
Each key is split into two points, which respectively represent the selected and unselected;
For the two keys I and j in each group, if I is selected, j cannot be selected. Similarly, if j is selected, I cannot be selected, then, for each set of two keys connected to two sides <I, not j> and <j, not I>;
For the two locks u and v on each door, if you do not select u, You must select v. If you do not select v, You must select u. Therefore, for each door, two sides are connected. <I is not, j> and <Non-j, I>,
Note that if the two locks on the door are the same, the key is required, then the edge is <non I, I>.
POJ 2749
The question seems to have two points s1 and s2 on the plane. These two points are connected and n points are given, then these points must be connected to either s1 or s2, and the maximum distance between any two points must be the minimum. Then, some points cannot be connected to the same side, that is, s1 or s2 at the same time, some points must be connected to the same side, that is, s1 or s2 at the same time. This requires the distance between Manhattan. There are four kinds of distances between two vertices a and B, a-> s1-> B; a-> s2-> B; a-> s1-> s2-> B; a-> s2-> s1-> B.
First, we can see that the maximum and minimum values must be the second answer. Then the 2-SAT model is obvious. Each vertex is split into two vertices, indicating that s1 and S2.
I made the above-mentioned AB non-conflict and edge AB error in the creation of this question, A whole DSP class is trying to create a graph model and then draw four or five of them.
The method of creating a graph is to first connect the required vertices that cannot be included with the sum of the vertices on the other side, and then enumerate each pair of vertices to create an edge in four situations, the code here may be clear:
for(i=0;i<n;i++)for(j=i+1;j<n;j++){ if(fd[i]+fd[j]>mid) { addedge(i*2,j*2+1); addedge(j*2,i*2+1); } if(fd[i]+dss+fe[j]>mid) { addedge(i*2,j*2); addedge(j*2+1,i*2+1); } if(fe[i]+dss+fd[j]>mid) { addedge(i*2+1,j*2+1); addedge(j*2,i*2); } if(fe[i]+fe[j]>mid) { addedge(i*2+1,j*2); addedge(j*2+1,i*2); }}
Here, fd [I] AND fe [I] represent the distance between point I and s1 s2, and dss represents the distance between s1 and s2. Then there is 2-sat verification.
POJ 3207
At the time of writing this question, I have not prepared my own 2-SAT template, but I still copied it from others. I still feel comfortable with my own code.
Question: There are n points in a circle from 0 to n-1 in sequence, and then there are m lines. Each line segment uses two of them as the endpoint. The line can be on the positive or back of the circle, whether there is a way to make any two line segments do not intersection, the endpoint intersection is not counted.
Each line is either on the front or back to create a 2-sat model, so the question is how to determine whether two line segments are intersecting. For two line segments x0, y0, x1, y1, ensure that x0 <y0 & x1 <y1 meets the following conditions, and the two lines cannot be on the same surface:
(X0-x1) * (x0-y1) * (y0-x1) * (y0-y1) <0
POJ 3648
This question is a 2-sat to be output.
A bunch of couples attend a wedding with a new couple. People sit on both sides of a long and long table (face to face ). The bride and groom are seated at the desk.
The bride does not want to see a couple sitting in the opposite row (the couple needs to have two separate seats ).
At the same time, some people have an ambiguous relationship (the same sex is possible), and the bride does not want to sit in the opposite row of her.
Ask if you can meet the requirements of the bride. If you can, provide a solution.
Region ~ It is hard to say that someone else's answer is copied directly.
Each husband and wife can only sit on the other side of the bride, and each couple can be a group of points. Two people with an ambiguous relationship cannot sit on the opposite side of the bride at the same time. This creates a diagram of the contradiction. Then the groom and the bride cannot sit on the same side, so they need to point one side from the groom to the bride.
This question is intended to be output, and this part is also a template, which is described in the paper.
POJ 3678
Create a series of 01 characters with a length of N, so that the I-and j-bits pass through a specific logical operation and the result is k.
Each group of points represents 0 and 1 respectively, and edge is created based on logical operations.
When I saw this question, I wanted to go to question B of the Changchun competition. If I had this question before the competition in Changchun, I would be able to quickly think of the question using 2-sat instead of generating brute force verification by bit, so it won't be WA for two hours.
POJ 3683
A priest wants to host N weddings. The length of the chair is x, which cannot be interrupted. You can host the wedding at the beginning or at the end of the wedding, that is, the start time + x or the end time-x to the end time. One wedding can end immediately after another wedding.
Creating a diagram based on whether the host starts and ends at the same time is overlapping. It is annoying to create a diagram for this question. There are four overlapping methods for the two weddings. When doing this question, I thought about the incorrect graph creation, what I want is to directly connect the edge without conflict, and the result is WA. In addition, this question also needs to be output.
There are a total of 8 2-SAT questions on POJ, and two other questions are POJ2296 and POJ3905. I have not written the TAT questions.
Appendix 2-SAT Template
//POJ 3683#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <iostream>#include <string>#include <algorithm>#include <queue>#include <map>#include <stack>using namespace std;#define PI acos(-1)#define INF 1<<30#define EPS 1e-6#define SET(a,b) memset(a,b,sizeof(a))#define N 2010#define M 4000010int n,m;int head[N],next[M],e[M],cnt;int nhead[N],nnext[M],ne[M],ncnt;int shead[N],snext[M],se[M],scnt;int dfn[N],low[N],step,point,ins[N];stack<int> st;int into[N],color[N],color2[N];int tl[N][2],tr[N][2],sp[N];int ts[N],tt[N];void addedge(int *head,int *next,int *e,int &cnt,int u,int v){next[cnt]=head[u];e[cnt]=v;head[u]=cnt++;}void tarjan(int u){int i,j,v;dfn[u]=low[u]=++step;st.push(u);ins[u]=1;for(i=head[u];i!=-1;i=next[i]){v=e[i];if(! dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}elseif(ins[v]) low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){do{j=st.top();st.pop();color[j]=point;ins[j]=0;} while (j!=u);point++;}}bool twosat(int n){for(int i=0;i+1<n;i+=2)if(color[i]==color[i+1]) return 0;return 1;}void COLOR(int s){color2[s]=1;for(int i=nhead[s];i!=-1;i=nnext[i])if(color2[ne[i]]==-1) COLOR(ne[i]);}void findans(int n){memset(into,0,sizeof(into));memset(color2,-1,sizeof(color2));memset(shead,-1,sizeof(shead));scnt=0;for(int i=0;i<n;i++)addedge(shead,snext,se,scnt,color[i],i);ncnt=0;memset(nhead,-1,sizeof(nhead));for(int i=0;i<n;i++)for(int j=head[i];j!=-1;j=next[j])if(color[i]!=color[e[j]]){addedge(nhead,nnext,ne,ncnt,color[e[j]],color[i]);into[color[i]]++;}queue<int> Q;for(int i=0;i<point;i++)if(into[i]==0) Q.push(i);while (! Q.empty()){int x=Q.front();Q.pop();if(color2[x]!=-1) continue;color2[x]=0;for(int i=nhead[x];i!=-1;i=nnext[i]){into[ne[i]]--;if(into[ne[i]]==0) Q.push(ne[i]);}for(int i=shead[x];i!=-1;i=snext[i])if(color2[color[se[i]^1]]==-1) COLOR(color[se[i]^1]);}memset(color,0,sizeof(color));for(int i=0;i<point;i++)if(color2[i]==1)for(int j=shead[i];j!=-1;j=snext[j]) color[se[j]]=1;for(int i=0;i<n;i++)if(color[i]==0){if(i%2==0){printf("%02d:%02d ",tl[i/2][0],tl[i/2][1]);printf("%02d:%02d\n",(ts[i/2]+sp[i/2])/60,(ts[i/2]+sp[i/2])%60);}else{printf("%02d:%02d",(tt[i/2]-sp[i/2])/60,(tt[i/2]-sp[i/2])%60);printf(" %02d:%02d\n",tr[i/2][0],tr[i/2][1]);}}}int main (){while(scanf("%d",&n)!=-1){for(int i=0;i<n;i++){scanf("%d:%d %d:%d %d",&tl[i][0],&tl[i][1],&tr[i][0],&tr[i][1],&sp[i]);ts[i]=tl[i][0]*60+tl[i][1];tt[i]=tr[i][0]*60+tr[i][1];}memset(head,-1,sizeof(head));cnt=0;for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(i!=j){if(ts[i]<=ts[j] && ts[i]+sp[i]>ts[j] || ts[i]<ts[j]+sp[j] && ts[i]+sp[i]>=ts[j]+sp[j]){addedge(head,next,e,cnt,i*2,j*2+1);addedge(head,next,e,cnt,j*2,i*2+1);}if(ts[i]<tt[j] && ts[i]+sp[i]>=tt[j] || ts[i]<=tt[j]-sp[j] && ts[i]+sp[i]>tt[j]-sp[j]){addedge(head,next,e,cnt,i*2,j*2);addedge(head,next,e,cnt,j*2+1,i*2+1);}if(tt[i]-sp[i]<=ts[j] && tt[i]>ts[j] || tt[i]-sp[i]<ts[j]+sp[j] && tt[i]>=ts[j]+sp[j]){addedge(head,next,e,cnt,i*2+1,j*2+1);addedge(head,next,e,cnt,j*2,i*2);}if(tt[i]-sp[i]<tt[j] && tt[i]>=tt[j] || tt[i]-sp[i]<=tt[j]-sp[j] && tt[i]>tt[j]-sp[j]){addedge(head,next,e,cnt,i*2+1,j*2);addedge(head,next,e,cnt,j*2+1,i*2);}}/*for(int i=0;i<n*2;i++)for(int j=head[i];j!=-1;j=next[j])printf("%d %d\n",i,e[j]);*/point=step=0;memset(dfn,0,sizeof(dfn));for(int i=0;i<n*2;i++)if(! dfn[i]) tarjan(i);//for(int i=0;i<n*2;i++) printf("%d ",color[i]); printf("\n");if(! twosat(n*2)) printf("NO\n");else{printf("YES\n");findans(2*n);}}return 0;}