2-satisfiability,我们一般将其缩写为 2-sat。

 

了解全名有助于我们对这个算法的理解。     百度翻译:satisfiability’---“可满足性,适定性”。

 

合取范式可满足性问题(简称SAT问题)是一个NP完全问题

          由于SAT问题目前是NP问题,所以自然有最大化满足性问题———MAX-SAT。

          然后也有最基本的问题,生存or死亡,嫁给我or吃屎———2-SAT。

如果能解决k-sat问题,那么他一定会火,毕竟没有很好的算法去解决,目前我们研究得更多是2-sat。

之前做的两个2-sat题:nmphy的2-sat。第三个是今天做的,整理一下。

 

-----------------------------------------------------我是分界线----------------------------------------------------------------

 

浅谈2-sat:(假设读者已经知道了2sat的原理,只是有时会乱,不知道把谁作为点,谁作为边,不知道怎么建图是好)

一般会有两个或者多个限制,要选择其中一个作为不相容限制。

然后其他的条件作为有向图,然后判环:

 

【关键】:整个算法转化成图的关键就是找好对象,判断出哪个作为不相容限制

如果不相容限制的两个子都不能满足,那么结果为false。

        【不相容限制】:n个被选择,每个是‘真’or‘假’,代表二者不能同时存在。

        【选择限制】:m个要求,一般牵涉到两个不相容限制。

        判断是哪种限制:不相容限制再每个集合都存在,而选择限制不是。

 

 

【例一】

(HDU1814):题目大意:一国有n个党派,每个党派在议会中都有2个代表,现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会。已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委员会的成员,现要你判断满足要求的和平委员会能否创立?如果能,请任意给出一种方案。

             【不相容限制】 是每个党派的代表,设为1,2。去了一个,另一个就不能去,每个党派(集合)都存在这样的关系。

            【选择限制】     是存在仇恨的代表,并不是所有党派或者代表都存在这样的关系。

 附上代码和注释

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
#define R 1//red 为ok 
#define B 2//black 访问过但不ok 
#define W 0//white 待染色 
const int maxn = 16005;
vector<int>G[maxn];
int cnt,col[maxn],ans[maxn],n,m;
bool dfs(int u)
{
    if (col[u] == B) return false;
    if (col[u] == R) return true;
    col[u] = R;col[u^1] = B;ans[cnt++]=u;//记录染了哪些,以便失败后把颜色改回来 
    for(int i=0;i<G[u].size();i++)
        if (!dfs(G[u][i])) return false;
    return true;
}
bool _solve()
{
    int i, j;
    memset(col,0,sizeof(col));
    for (i=0; i<n; i++){
        if (col[i]) continue;
        cnt=0;
        if (!dfs(i)){
            for (j=0;j<cnt;j++){
                col[ans[j]]=W;//漂白 
                col[ans[j]^1]=W;//漂白 
            }
            if (!dfs(i^1))  return false;//2-sat失败 
        }
    }
    return true;
}
int main()
{ 
    int i,a,b;
    while (~scanf("%d %d",&n, &m)){
        n<<=1;   
        for(i=0;i<=n;i++) G[i].clear();
        while (m--){
            scanf("%d %d",&a, &b);
            a--;b--;
            G[a].push_back(b^1);
            G[b].push_back(a^1);
        }
        if (_solve()){
            for (i=0; i<n; i++)
                if(col[i] == R)
                    printf("%d\n",i+1);
        }
        else printf("NIE\n");
    }
    return 0;
}
View Code

相关文章:

  • 2022-01-13
猜你喜欢
  • 2021-06-28
  • 2021-06-06
  • 2022-02-03
相关资源
相似解决方案