【小结】2-sat

2?sat 小结

  • 2?sat解决的是可满足性问题,并且每个合取范式中的文字个数不多于2个。
  • 形式为: (a∨?b)∧(?c∨?d)∧(?a∨d)?
  • 将所有a∨b改成(?a?b)∧(?b?a)
  • 建边,每个变量a对应两个点a和a+n
  • 如果存在cmp[a]==cmp[a+n]不成立,否则成立。且如果cmp[a]>cmp[a+n],令a=true,否则令a=false即为原式的一组解。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int MAX = 1024;
vector<int> G[MAX];
vector<int> rG[MAX];
stack<int> S;
bool vis[MAX];
int cmp[MAX];
int V;

inline void add_edge(int u, int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}

void dfs(int v)
{
    vis[v] = true;
    for (vector<int>::iterator it = G[v].begin(); it != G[v].end(); ++it)
    {
        if (!vis[*it])
        {
            dfs(*it);
        }
    }

    S.push(v);
}

void rdfs(int v, int k)
{
    vis[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); ++i)
    {
        if (!vis[rG[v][i]])
        {
            rdfs(rG[v][i], k);
        }
    }
}

int scc()
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= V; ++i)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }

    memset(vis, false, sizeof(vis));
    int k = 0;

    while (!S.empty())
    {
        int p = S.top();
        S.pop();

        if (!vis[p])
        {
            rdfs(p, ++k);
        }
    }

    return k;
}

int main()
{

    /*
     * add_edge(u, v)
     * N nodes --> V = 2 * N
     * ...
     */
    /*
     * EXAMPLE: solve (a V !b) ^ (b V c) ^ (!c V !a)
     */
    int N = 3;
    V = N << 1;

    add_edge(3, 4);
    add_edge(1, 0);
    add_edge(4, 2);
    add_edge(5, 1);
    add_edge(2, 3);
    add_edge(0, 5);

    scc();

    bool ok = true;
    for (int i = 1; i <= N; ++i)
    {
        if (cmp[i] == cmp[i + N])
        {
            ok = false;
            break;
        }
    }

    if (ok)
    {
        puts("YES");
        for (int i = 1; i <= N; ++i)
        {
            printf("%s ", cmp[i] > cmp[i + N] ? "true" : "false");
        }
        puts("");
    }
    else
    {
        puts("NO");
    }

    return 0;
}

POJ3683 Priest John′s Busiest Day

  • 问牧师能不能忙过来
  • 对婚礼x,记在开始举行仪式为x=true,则可根据冲突关系,得出方程,求解即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int MAX = 2048;
vector<int> G[MAX];
vector<int> rG[MAX];
stack<int> stk;
bool vis[MAX];
int cmp[MAX];
int V;

inline void init()
{
    for (int i = 1; i <= V; ++i)
    {
        G[i].clear();
        rG[i].clear();
    }
}

inline void add_edge(int u, int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}

void dfs(int u)
{
    vis[u] = true;
    for (int i = 0; i < G[u].size(); ++i)
    {
        if (!vis[G[u][i]])
        {
            dfs(G[u][i]);
        }
    }
    stk.push(u);
}

void rdfs(int u, int k)
{
    vis[u] = true;
    cmp[u] = k;
    for (int i = 0; i < rG[u].size(); ++i)
    {
        if (!vis[rG[u][i]])
        {
            rdfs(rG[u][i], k);
        }
    }
}

int scc()
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= V; ++i)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }

    memset(vis, false, sizeof(vis));
    int k = 0;
    while (!stk.empty())
    {
        int p = stk.top();
        stk.pop();

        if (!vis[p])
        {
            rdfs(p, ++k);
        }
    }

    return k;
}

int S[MAX >> 1], T[MAX >> 1], D[MAX >> 1];

inline bool error(int l1, int r1, int l2, int r2)
{
    return l1 > l2 ? r2 > l1 : r1 > l2;
}

void gao(int n)
{
    V = n << 1;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = i + 1; j <= n; ++j)
        {
            if (error(S[i], S[i] + D[i], S[j], S[j] + D[j]))
            {
                add_edge(i, j + n);
                add_edge(j, i + n);
            }
            if (error(S[i], S[i] + D[i], T[j] - D[j], T[j]))
            {
                add_edge(i, j);
                add_edge(j + n, i + n);
            }
            if (error(T[i] - D[i], T[i], S[j], S[j] + D[j]))
            {
                add_edge(i + n, j + n);
                add_edge(j, i);
            }
            if (error(T[i] - D[i], T[i], T[j] - D[j], T[j]))
            {
                add_edge(i + n, j);
                add_edge(j + n, i);
            }
        }
    }

    scc();
    //printf("%d\n", scc()); //scc();

    for (int i = 1; i <= n; ++i)
    {
        if (cmp[i] == cmp[i + n])
        {
            puts("NO");
            return;
        }
    }

    puts("YES");
    for (int i = 1; i <= n; ++i)
    {
        if (cmp[i] > cmp[i + n])
        {
            printf("%02d:%02d %02d:%02d\n", S[i] / 60, S[i] % 60, (S[i] + D[i]) / 60, (S[i] + D[i]) % 60);
        }
        else
        {
            printf("%02d:%02d %02d:%02d\n", (T[i] - D[i]) / 60, (T[i] - D[i]) % 60, T[i] / 60, T[i] % 60);
        }
    }
}

int main()
{
    int N;
    while (~scanf(" %d", &N))
    {
        int h, m;
        for (int i = 1; i <= N; ++i)
        {
            scanf(" %d:%d", &h, &m);
            S[i] = h * 60 + m;
            scanf(" %d:%d", &h, &m);
            T[i] = h * 60 + m;
            scanf(" %d", D + i);

            //printf("%d:[%d, %d]:%d\n", i, S[i], T[i], D[i]);
        }
        gao(N);
    }
    return 0;
}

HDU3062

#include <bits/stdc++.h>
using namespace std;

const int MAX = 1024;
vector<int> G[MAX << 1];
vector<int> rG[MAX << 1];
bool vis[MAX << 1];
int cmp[MAX << 1];
stack<int> stk;
int V;

inline void add_edge(int u, int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}

void dfs(int u)
{
    vis[u] = true;
    for (int i = 0; i < G[u].size(); ++i)
    {
        if (!vis[G[u][i]])
        {
            dfs(G[u][i]);
        }
    }
    stk.push(u);
}

void dfs2(int u, int k)
{
    vis[u] = true;
    cmp[u] = k;
    for (int i = 0; i < rG[u].size(); ++i)
    {
        if (!vis[rG[u][i]])
        {
            dfs2(rG[u][i], k);
        }
    }
}

int scc()
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= V; ++i)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }

    memset(vis, false, sizeof(vis));
    int k = 0;
    while (!stk.empty())
    {
        int p = stk.top();
        stk.pop();

        if (!vis[p])
        {
            dfs2(p, ++k);
        }

    }
    return k;
}

bool gao(int n)
{
    scc();

    for (int i = 1; i <= n; ++i)
    {
        if (cmp[i] == cmp[i + n])
        {
            return false;
        }
    }
    return true;
}

inline void read(int& x)
{
    char ch;
    while ((ch = getchar()) < ‘0‘ || ch > ‘9‘);

    x = ch - ‘0‘;
    while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
    {
        x = (x << 3) + (x << 1) + ch - ‘0‘;
    }
}

int main()
{
    int n, m;
    while (~scanf(" %d %d", &n, &m))
    {
        V = n << 1;
        for (int i = 1; i <= V; ++i)
        {
            G[i].clear();
            rG[i].clear();
        }

        int a1, a2, c1, c2;
        while (m--)
        {
            //scanf(" %d %d %d %d", &a1, &a2, &c1, &c2);
            read(a1);
            read(a2);
            read(c1);
            read(c2);
            if (c1 > 0)
            {
                a1 += n;
            }
            if (c2 > 0)
            {
                a2 += n;
            }

            /*
             * !a1 V !a2
             * <->  ((a1 -> !a2) V (a2 -> !a1))
             */
            add_edge(a1, a2 > n ? a2 - n : a2 + n);
            add_edge(a2, a1 > n ? a1 - n : a1 + n);
        }
        puts(gao(n) ? "YES" : "NO");
    }
    return 0;
}

HDU 1824

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int MAX = 1024 * 3 * 2;
vector<int> G[MAX];
vector<int> rG[MAX];
stack<int> S;
bool vis[MAX];
int cmp[MAX];
int V;

inline void add_edge(int u, int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}

void dfs(int v)
{
    vis[v] = true;
    for (vector<int>::iterator it = G[v].begin(); it != G[v].end(); ++it)
    {
        if (!vis[*it])
        {
            dfs(*it);
        }
    }

    S.push(v);
}

void rdfs(int v, int k)
{
    vis[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); ++i)
    {
        if (!vis[rG[v][i]])
        {
            rdfs(rG[v][i], k);
        }
    }
}

int scc()
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= V; ++i)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }

    memset(vis, false, sizeof(vis));
    int k = 0;

    while (!S.empty())
    {
        int p = S.top();
        S.pop();

        if (!vis[p])
        {
            rdfs(p, ++k);
        }
    }

    return k;
}

bool gao(int N)
{
    scc();

    for (int i = 1; i <= N; ++i)
    {
        if (cmp[i] == cmp[i + N])
        {
            return false;
        }
    }
    return true;
}

int main()
{
    int T, M;
    while (~scanf(" %d %d", &T, &M))
    {
        V = T * 3 * 2;
        int N = T * 3;
        for (int i = 0; i <= V; ++i)
        {
            G[i].clear();
            rG[i].clear();
        }

        int c, a, b;
        for (int i = 1; i <= T; ++i)
        {
            scanf(" %d %d %d", &c, &a, &b);
            ++c, ++a, ++b;
            add_edge(c + N, a);
            add_edge(c + N, b);

            add_edge(a + N, c);
            add_edge(b + N, c);

            add_edge(c, a + N);
            add_edge(c, b + N);
            add_edge(a, c + N);
            add_edge(b, c + N);
        }

        for (int i = 1; i <= M; ++i)
        {
            scanf(" %d %d", &a, &b);
            ++a, ++b;
            add_edge(a, b + N);
            add_edge(b, a + N);
        }

        puts(gao(N) ? "yes" : "no");
    }

    return 0;
}

POJ 3207

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int MAX = 1024;
vector<int> G[MAX];
vector<int> rG[MAX];
stack<int> S;
bool vis[MAX];
int cmp[MAX];
pair<int, int> line[MAX >> 1];
int V;

inline void add_edge(int u, int v)
{
    G[u].push_back(v);
    rG[v].push_back(u);
}

void dfs(int v)
{
    vis[v] = true;
    for (vector<int>::iterator it = G[v].begin(); it != G[v].end(); ++it)
    {
        if (!vis[*it])
        {
            dfs(*it);
        }
    }

    S.push(v);
}

void rdfs(int v, int k)
{
    vis[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); ++i)
    {
        if (!vis[rG[v][i]])
        {
            rdfs(rG[v][i], k);
        }
    }
}

int scc()
{
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= V; ++i)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }

    memset(vis, false, sizeof(vis));
    int k = 0;

    while (!S.empty())
    {
        int p = S.top();
        S.pop();

        if (!vis[p])
        {
            rdfs(p, ++k);
        }
    }

    return k;
}

bool gao(int n)
{

    scc();

    for (int i = 1; i <= n; ++i)
    {
        if (cmp[i] == cmp[i + n])
        {
            return false;
        }
    }

    return true;
}

bool error(int x1, int y1, int x2, int y2)
{
    int xx = min(x1, y1);
    int yy = min(x1, y1);
    return (x2 > xx && x2 > yy) || (y2 > xx && y2 > yy)
        || (x2 > xx && x2 < yy) || (y2 > xx && y2 < yy)
        || (x2 < xx && x2 < yy) || (y2 < xx && y2 < yy);
}

int main()
{
    int n, m;
    while (~scanf(" %d %d", &n, &m))
    {
        V = m << 1;
        for (int i = 1; i <= V; ++i)
        {
            G[i].clear();
            rG[i].clear();
        }
        int a, b;
        for (int i = 1; i <= m; ++i)
        {
            scanf(" %d %d", &line[i].first, &line[i].second);
            ++line[i].first, ++line[i].second;
        }

        for (int i = 1; i <= m; ++i)
        {
            for (int j = i + 1; j <= m; ++j)
            {
                if (error(line[i].first, line[i].second, line[j].first, line[j].second))
                {
                    printf("error at (%d, %d)\n", i, j);
                    //add_edge
                    add_edge(i, j + m);
                    add_edge(j, i + m);
                }
            }
        }

        puts(gao(m) ? "panda is telling the truth..." : "the evil panda is lying again");
        for (int i = 1; i <= m; ++i)
        {
            if (cmp[i] > cmp[i + m])
            {
                printf("true ");
            }
            else
            {
                printf("false ");
            }
        }
        puts("");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 02:26:10

【小结】2-sat的相关文章

2017年informix小结

2017年informix小结,相关内容已经脱敏,需要脚本源码,请和我联系. # w01 - OS基本信息及负载情况 IBM Informix Dynamic Server Version 11.50.FC9W3 -- On-Line -- Up 5 days 18:29:27 -- 45931492 Kbytes Machine Configuration.... OS Name HP-UX OS Release B.11.31 OS Node Name xxxxxxxxx OS Versio

2-SAT 问题与解法小结

2-SAT 问题与解法小结 这个算法十分的奇妙qwq... 将一类判定问题转换为图论问题,然后就很容易解决了. 本文有一些地方摘录了一下赵爽<2-SAT解法浅析> (侵删) 一些概念: \(SAT\)问题:就是给一些布尔变量赋值,使得所有给你的条件成立的问题---适定性(Satisfiability)问题.我们令\(k\)为所有条件中含有变量的最大值,那么我们就可以称其为\(k-SAT\)问题. 可以证明\(k>2\)时候为NP完全问题,而\(k=2\)的时候存在多项式解法. \(2-S

使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI导出Excel小结--导出XLSX格式文档 使用Apache POI导出Excel--大数量导出 导出XLS格式文档 做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考.关于Apache POI Excel基本的概念与操作我在这里就不啰嗦

【转载】小结一下linux 2.6内核的四种IO调度算法

在LINUX 2.6中,有四种关于IO的调度算法,下面综合小结一下: 1) NOOP NOOP算法的全写为No Operation.该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作.之所以说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求.NOOP假定I/O请求由驱动程序或者设备做了优化或者重排了顺序(就像一个智能控制器完成的工作那样).在有些SAN环境下,这个选择可能是最好选择.Noop 对于 IO

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert

安卓小结《1》

Activity的生命周期和启动模式的知识点小结: 1.如果Activity切换的时候,新Activity是透明,旧的不会走onStop方法. 2.新的Activity切换的时候,旧Activity  会先执行,onpause,然后才会启动新的activity. 3. Activity在异常情况下被回收时,onSaveInstanceState方法会被回调,回调时机是在onStop之前,当Activity被重新创建的时 候,onRestoreInstanceState方法会被回调,时序在onSt

date命令小结

在写linux shell脚本时,date是经常要用到的一个命令,这篇文章就此做个小结,以防自己用到时到处找 1.最基本的,显示当前的具体时期:直接敲入 date即可,如下, [email protected]:~/scripts$ date 2015年 01月 03日 星期六 21:46:49 CST 2.显示某个文件上次修改的时间:date -r file [email protected]:~/scripts$ date -r save.sh 2015年 01月 02日 星期五 23:29

java 小结2 多态问题。

面向对象这个东西,其实我们一直是不是都没有感觉到自己在用,以后我一定要用用.以前学c#时候认真的看过一次,最近一直研究java.随便再看看. 多态问题: 在java中多态分为(1)编译时多态和(2)运行时多态 (1)编译时多态比较容易理解:其实就是通过方法重载,就是方法的重载,同一个函数名但是可以参数不一样.这就是重载(so easy) (2)运行时多态:这个是通过方法覆盖实现的,就是子类在继承父类的时候,通过对某个方法的重写,覆盖父类方法. 简单的说:比如我们有个父类A,子类B通过Extend