题解 P4782 【【模板】2-SAT 问题】
Great_Influence · · 题解
2-sat
建边
意义显然。如果
2. x_i=a 与 x_j=b 至少满足一个
建边
同样十分显然。如果
3. x_i=a 一定满足
建边
考虑该操作的意义。首先可以知道,
可以证明,以上
经过操作后,你就得到了一张有向图。开始考虑这张图的作用。
首先,对于这张图中的每个强连通分量中的点一定要么同时选,要么同时不选。
那么,我们将图缩强连通分量。
这时候就可以判断无解了。如果
此时,你就得到了一张拓扑图。这张拓扑图中,如果
那么,你可以利用强连通分量的标号来得到反向的拓扑序。
再结合上面的性质,可以得到一个选择策略:
在
这样就可以避免产生冲突了。并且这种方法一定可以构造出解。
这样
核心代码:
static int dfn[MAXN<<1],low[MAXN<<1],bel[MAXN<<1];
static int e,cnt,sta[MAXN<<1],tp;
void tarjan(int u)
{
dfn[u]=low[u]=++e;sta[++tp]=u;
for(register int v:ed[u])
{
if(!dfn[v])tarjan(v),Chkmin(low[u],low[v]);
else if(!bel[v])Chkmin(low[u],dfn[v]);
}
if(low[u]==dfn[u])for(++cnt;sta[tp+1]^u;--tp)
bel[sta[tp]]=cnt;
}
inline void solve()
{
Rep(i,2,n<<1|1)if(!dfn[i])tarjan(i);
Rep(i,1,n)if(bel[i<<1]==bel[i<<1|1])return (void)puts("IMPOSSIBLE");
puts("POSSIBLE");
Rep(i,1,n)write(bel[i<<1]>bel[i<<1|1],' ');
}