Qaq is the most difficult question to write so many simulation questions.
Good God, so I made up and checked the set ..
And the query set is very god ......
Orz
Type and query set... Orz
To maintain the SAT, we can think like this:
If the XOR values of X and Y are true, then X and Y are definitely different. Then we have s [x] = s [y] ^ 1.
Otherwise, s [x] = s [y]
We need to maintain a series of relationships between x and y, so we should consider using and querying sets to maintain this interval!
Note that this must be the concept of Interval!
Because only the interval can satisfy the interval nature!
For example
X xor y XOR z = true
We know the value of x xor y, so we can know the value of x xor z!
Therefore, x y z can be seen as a chain of the query set, then let's assume that at first we only know that y XOR z = true, then the edge Fa [y] = Z and then s [y] = s [x] ^ 1
So when we know that x xor y = true, we can convert Fa [x] = y and then s [x] = s [y] ^ 1
The current figure is
X-> Y-> Z
We can try to compress the path from X to Z so that the value of X-> Z is Fa [x] = Z, s [x] ^ = s [y] That is, x xor z = false
It's amazing. No ..
Now let's redefine the S array!
S [I] indicates the XOR value of the tree root from I to I (and query the set ).
Therefore, based on the XOR nature, we can write this in path compression.
Int F = find (Fa [x]); s [x] ^ = s [Fa [x]; P [x] = F;
So we can maintain the S! Again, s indicates the XOR value from X to the root of the tree! Not its real value! (Otherwise, just like me, I couldn't figure it out at the beginning ...)
Then, when merging, it is similar to the query set, but we only need to maintain S. That is
FX = find (x), FY = find (y)
If (FX! = FY & (x XOR y = true) P [FX] = FY; s [FX] = s [x] ^ s [y] ^ 1; // The reason for doing so is very simple. Think about it yourself .. It is based on x xor y = true/false and x xor fx = true/false and y xor fy = true/false. Now you only need to know fx xor fy = ?.. Note that it must not be s [FY] =... because you can see the definition of S .... If it is s [FY] =, P [FX] will be messy...
When x XOR y = false, it is also very simple. s [FX] = s [x] ^ s [y]
If there is no solution, then there is no solution if FX = FY and the value from X to fx and Y to FY does not match the value of x xor y given...
The construction solution is also very simple. Let's assume that all the roots are true.
Then the problem is simple ....
After the path is compressed, each node to the root is a path, so we know that the root is true .. So .. You don't have ..
#include <cstdio>#include <cstring>#include <cmath>#include <string>#include <iostream>#include <algorithm>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;#define pii pair<int, int>#define mkpii make_pair<int, int>#define pdi pair<double, int>#define mkpdi make_pair<double, int>#define pli pair<ll, int>#define mkpli make_pair<ll, int>#define rep(i, n) for(int i=0; i<(n); ++i)#define for1(i,a,n) for(int i=(a);i<=(n);++i)#define for2(i,a,n) for(int i=(a);i<(n);++i)#define for3(i,a,n) for(int i=(a);i>=(n);--i)#define for4(i,a,n) for(int i=(a);i>(n);--i)#define CC(i,a) memset(i,a,sizeof(i))#define read(a) a=getint()#define print(a) printf("%d", a)#define dbg(x) cout << (#x) << " = " << (x) << endl#define error(x) (!(x)?puts("error"):0)#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }#define printarr1(a, b) for1(_, 1, b) cout << a[_] << ‘\t‘; cout << endlinline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }inline const int max(const int &a, const int &b) { return a>b?a:b; }inline const int min(const int &a, const int &b) { return a<b?a:b; }const int N=1000005;int p[N], s[N], n, m;char c[10];const int ifind(const int x) {if(x==p[x]) return x;int f=ifind(p[x]);s[x]^=s[p[x]];return p[x]=f;}int main() {read(n); read(m);for1(i, 1, n) p[i]=i;for1(i, 1, m) {int x=getint(), y=getint(), fx=ifind(x), fy=ifind(y);scanf("%s", c);if(c[0]==‘T‘) {if(fx==fy && s[x]==s[y]) { puts("Impossible"); return 0; }if(fx!=fy) p[fx]=fy, s[fx]=s[x]^s[y]^1;}else {if(fx==fy && s[x]!=s[y]) { puts("Impossible"); return 0; }if(fx!=fy) p[fx]=fy, s[fx]=s[x]^s[y];}}puts("Possible");for1(i, 1, n) ifind(i);for1(i, 1, n) if(i==p[i]) puts("TRUE"); else s[i]?puts("FALSE"):puts("TRUE");return 0;}
2-xor-sat
[Description]
Satisfiability is a well-known NP complete problem. Its content is:
It is limited to true for a Boolean variable and its expression group connected by the "not" operation "or" operation.
2-The SAT question imposes the following restrictions on the SAT question: each expression is composed of two variables.
XOR-SAT issues impose the following limits on SAT problems: expressions are only composed of variables and "XOR" operations.
2-xor-sat contains the preceding two restrictions: There are n Boolean variables X 1... x n and M double variables.
Variance or Equation
X a 1 XOR x B 1 = C 1
X a 2 XOR x B 2 = C 2
{
?
X a m xor x B M = C m
You need to determine whether the equations have solutions. If there are solutions, please output any group of solutions; otherwise, no solutions are output.
[Input file]
The first line has two integers, n m.
In the next m row, each row has two integers, a I and an uppercase string c I. c I is "true" or "false"
[Output file]
If no solution is available, a line of "impossible" is output"
If there is a solution, the first line outputs "possible", and the next n rows output the value of X 1... x n "true" or "false"
[Example input]
3 2
1 2 true
2 3 false
[Sample output]
Possible
False
True
True [data range]
30% of Data guarantee n ≤ 20; m ≤ 20
100% of data is guaranteed to be 1 ≤ n ≤ 100,000; 1 ≤ m ≤ 100,000
2-xor-sat (type and query set)