Labels: point-to-point (MAT) cannot be reduced. In many ways, how can Lin assign values?
P4782 [TEMPLATE] 2-SAT problems
Question Background
\ (2-sat \) question Template
Description
There are \ (n \) Boolean variables \ (X_1 \ SIM x_n \), and \ (M \) conditions to be met, the format of each condition is "\ (x_ I \) is \ (true/false \) or \ (x_j \) is \ (true/false \)". For example, "\ (X_1 \) is true or \ (X_3 \) is false", "\ (x_7 \) is false or \ (X_2 \) is false ". The objective of the \ (2-sat \) problem is to assign values to each variable so that all conditions are satisfied.
Input/output format:
The first line has two integers \ (n \) and \ (M \), meaning as described in the question.
The next \ (M \) line contains \ (4 \) integers \ (I \ A \ J \ B \), indicating that \ (x_ I \) is \ (\) or \ (x_j \) is \ (B \) "\ (a, B \ In \ {0, 1 \})\)
Output Format:
If no solution is available, output"IMPOSSIBLE"
(Without quotation marks); otherwise, output"POSSIBLE"
(Without quotation marks), the next line \ (n \) integer \ (X_1 \ SIM X_n (x_ I \ In \ {0, 1 \}) \) represents the constructed solution.
Input and Output sample input sample #1:
3 11 1 3 0
Output sample #1:
POSSIBLE0 0 0
Ideas
Learn now \ (2-sat \), so that you can play the game [noi2017. -- Huyufeifei
\ (2-sat \) is a type of problem that I like very much. First, it uses my favorite \ (Tarjan \) algorithm.
Second, it uses the algorithm implemented by logical judgment, which is also very popular.
For each \ (x_ I \), we create two vertices, numbered \ (I \) and \ (I + n \), \ (I \) \ (x_ I = 1 \) and \ (I + n \) indicate \ (x_ I = 0. Next we will consider creating edges for each pair of logical relationships. Here, for the universality of the problem, we will not only consider the conditions listed in the questions, but also try to consider more situations.
- \ (A \) True: Creates an edge \ (a + N, A) \), which indicates that if \ (A \) is false, \ (A \) is true. In this way, \ (A \) can be finally pushed to the actual situation.
- If \ (A \) is true, \ (B \) is false: Create two edges: \ (A, B + n), (B, A + n )\).
- \ (A \) is true and \ (B \) is false and must satisfy at least one: Create two sides: \ (a + N, B + n), (B, )\).
- \ (A \) is true and \ (B \) is false and cannot satisfy both: Create two edges: \ (A, B), (B + N, A + n )\).
There are still many cases where enumeration is not available, but they are similar to the above content and will not be listed here.
What should we do next? According to the method of EDGE connection, it is not difficult to find the edge.Push and exportThat is to say, if \ (A \) can reach \ (B \) through some paths, this indicates \ (\) if the \ (B \) condition can be used, \ (B \) must be satisfied if \ (A \) is satisfied. If \ (a, B \) can reach each other, it means that the two are either satisfied or not satisfied at the same time.
It is not hard to come up with. There is only one case that there is no solution: \ (A \) and \ (a + n \) can reach each other, that is, two conflicting conditions can push and export each other. Use the \ (Tarjan \) contraction point to quickly determine whether any two points can arrive at each other and determine the existence of the solution.
How can we determine the value of each variable? If you can export \ (a + n \) from \ (A \), we obviously cannot select \ (A \), but can only select \ (a + n \). Therefore, for the two values of the same variable, we need to check whether there is a derivation relationship between them. According to the characteristics of the \ (Tarjan \) algorithm, if \ (A \) can reach \ (B \) and \ (a, B \) is not in the same shrinkage point, the number of the point where \ (B \) is scaled down must be smaller than \ (\). If \ (A \) cannot reach \ (B \), it is difficult to judge the number of the contraction points between the two. Of course, since we only need to obtain any group of solutions, for each pair of \ (A, A + n) \), we can output a smaller vertex number.
AC code
#include<bits/stdc++.h>using namespace std;const int MAXN=2e6+5;int n,m,tot,dfn[MAXN],low[MAXN];int cnt,top[MAXN],to[MAXN],nex[MAXN];int js,bel[MAXN];bool vis[MAXN];stack<int>S;int read(){ int re=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar(); return re;}void add_edge(int x,int y){to[++cnt]=y,nex[cnt]=top[x],top[x]=cnt;}void tarjan(int now){ dfn[now]=low[now]=++tot,vis[now]=true; S.push(now); for(int i=top[now];i;i=nex[i]) if(!dfn[to[i]]) tarjan(to[i]),low[now]=min(low[now],low[to[i]]); else if(vis[to[i]]) low[now]=min(low[now],dfn[to[i]]); if(dfn[now]==low[now]) { bel[now]=++js,vis[now]=false; while(S.top()!=now) bel[S.top()]=js,vis[S.top()]=false,S.pop(); S.pop(); }}int main(){ n=read(),m=read(); while(m--) { int x=read(),xx=read(),y=read(),yy=read(); if(xx&&yy) add_edge(x+n,y),add_edge(y+n,x); else if(xx&&!yy) add_edge(x+n,y+n),add_edge(y,x); else if(!xx&&yy) add_edge(x,y),add_edge(y+n,x+n); else if(!xx&&!yy) add_edge(x,y+n),add_edge(y,x+n); } for(int i=1;i<=(n<<1);i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) if(bel[i]==bel[i+n]) { printf("IMPOSSIBLE"); return 0; } puts("POSSIBLE"); for(int i=1;i<=n;i++) printf("%d ",bel[i]<bel[i+n]); return 0;}
Luogu p4782 [TEMPLATE] 2-Sat (2-Sat)