P4782 模板 2 SAT 問題

2022-02-27 21:42:47 字數 1389 閱讀 3231

傳送門

2-sat的板子

把每乙個點拆成選0或選1

條件為$x_i$為$a$或$x_j$為$b$,那麼如果$x_i$不為$a$則$x_j$必為$b$,同理$x_j$不為$b$則$x_i$必為$a$

那麼從$x_i$不為$a$的點向$x_j$為$b$的點連邊,從$x_j$不為$b$的點向$x_i$為$a$的點連邊

然後跑乙個tarjan縮點,在新的dag的反圖上跑一遍拓撲排序,如果有乙個點的兩個取值在同乙個強連通分量裡就無解,否則取兩個取值中拓撲序小的那乙個

有乙個小技巧就是tarjan縮點時的編號實際就是新的dag的反圖拓撲序,那麼只要看兩個取值誰的拓撲序更小取誰就行了

1

//minamoto

2 #include3 #include4

using

namespace

std;

5#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)

6char buf[1

<<21],*p1=buf,*p2=buf;

7 templateinline bool cmin(t&a,const t&b)

8 inline int

read()

18char sr[1

<<21],z[20];int c=-1

,z;19 inline void ot()

20 inline void print(int

x)25

const

int n=2e6+5;26

inthead[n],next[n],ver[n],tot;

27 inline void add(int u,int

v)30

intdfn[n],bl[n],low[n],st[n],top,num,cnt,n,m;

31void tarjan(int

u)38

if(low[u]==dfn[u]) for(++cnt;st[top+1]!=u;--top) bl[st[top]]=cnt;39}

40int

main()

47for(int i=1,l=n<<1;i<=l;++i) if(!dfn[i]) tarjan(i);

48for(int i=1;i<=n;++i)

49if(bl[i]==bl[i+n]) return puts("

impossible

"),0

;50 puts("

possible");

51for(int i=1;i<=n;++i) print(bl[i+n]52ot();

53return0;

54 }

《P4782 模板 2 SAT 問題》

2 sat問題 就是一些元素,他們的值只能為布林值0,1.給出一些限制關係,並且每對關係都是兩個數之間的。讓你找出一組構造,讓所有關係都滿足。解法 首先要建圖 我們規定,a為1的點為a n,a為0的點為a。那麼對於給定的一對關係a b。如果是a 1,b 1,那麼說明a b。利用可以轉化為 a b,b...

題解 P4782 模板 2 SAT 問題

將每乙個點 x i 拆成 2i 和 2i 1 2i 表示 x i 的假狀態,2i 1 表示 x i 的真狀態 問題就化為了從2n個狀態中選出原來的每乙個 x i 的乙個狀態。這有什麼用呢?別急,先舉個栗子,1 1 3 0 就可以用有向邊 2 6 7 3 來表示,什麼意思呢?2表示1為false,根據...

題解 P4782 模板 2 SAT 問題

將每乙個點 x i 拆成 2i 和 2i 1 2i 表示 x i 的假狀態,2i 1 表示 x i 的真狀態 問題就化為了從2n個狀態中選出原來的每乙個 x i 的乙個狀態。這有什麼用呢?別急,先舉個栗子,1 1 3 0 就可以用有向邊 2 6 7 3 來表示,什麼意思呢?2表示1為false,根據...