2-sat模板

这是个无比暴力的模板

但是

从来没有没卡过!!!

判是否存在解

流程:标记i并传递标记,直到结束或出现矛盾。

bool mark[M];
int stk[M],top;
bool dfs(int x){
    if(mark[x^1])return 0;
    if(mark[x])return 1;
    mark[x]=1;
    stk[++top]=x;
    for(int i=head[x];i;i=G[i].nxt){
        if(!dfs(G[i].to))return 0;
    } 
    return 1;
}
bool check() {
    for(int i=0;i<n*2;i+=2){
        if(!mark[i]&&!mark[i+1]){
            top=0;
            if(!dfs(i)){
                while(top)mark[stk[top--]]=0;
                if(!dfs(i+1))return 0;
            }
        }
    }
    return 1;
}
输出方案
根据mark的定义输出即可
for(int i=0; i<2*n; i+=2) {
    if(mark[i]) {
        printf("%d",??);
    } else {
        printf("%d",??);
    }
}

还有一种方法 tarjan

流程:求出强连通分量,如果i*2和i*2+1在一个强连通分量里,则无解

void tarjan(int x){
   dfn[x]=low[x]=++tot;
    stk[++top]=x;
    vis[x]=1;
    for(int i=head[x]; i; i=G[i].nxt) {
        int y=G[i].to;
        if(!dfn[y]) {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        } else if(vis[y]) {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x]) {
        int y;
        cnt++;
        do {
            y=stk[top--];
            vis[y]=0;
            col[y]=cnt;
        } while(y!=x);
    } 
}
输出方案:
把强连通分量用反边连接,构成新图
按拓扑序标记选和不选,传递不选标记
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值