【2-sat】和平委员会

【2-sat】和平委员会_第1张图片


分析

本题有两种解法,其中解法1比较常规,可以很好的理解,复杂度也是很不错的 O(n) O ( n )
解法2在思想上更加简洁,粗略估计时间复杂度 O(n2) O ( n 2 ) 但实际上期望复杂度仅有 O(n1.5) O ( n 1.5 ) 最重要的是,代码复杂度相当低。我写的解法1有100行,而解法2只有60多行!考场上,解法2当然是最后关头的最佳选择。

解法1-强连通分量缩点+拓扑排序

解法2-暴力枚举搜索

#include
#include
#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
#define MAXN 16010
using namespace std;
vector<int> a[MAXN];
int n,m,p[MAXN];
bool used[MAXN];
stack<int> s;
vectorint,int> >l;
bool dfs(int x){
    if(used[p[x]]==1)
        return 0;
    if(used[x]==1)
        return 1;
    s.push(x);
    used[x]=1;
    for(int i=0;iif(dfs(a[x][i])==0)
            return 0;
    return 1;
}
bool check(){
    for(int i=1;i<=2*n;i++){
        if(used[i]==0&&used[p[i]]==0){
            while(!s.empty())
                s.pop();
            if(dfs(i)==0){
                while(!s.empty()){
                    used[s.top()]=0;
                    s.pop();
                }
                if(dfs(p[i])==0)
                    return 0;
            }
        }
    }
    return 1;
}
int main(){=
    SF("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=n;i++){
        p[i*2]=i*2-1;
        p[i*2-1]=i*2;
    }
    for(int i=1;i<=m;i++){
        SF("%d%d",&x,&y);
        a[x].push_back(p[y]);
        a[y].push_back(p[x]);
        l.push_back(make_pair(x,p[y]));
        l.push_back(make_pair(y,p[x]));
    }
    if(check()){
        for(int i=1;i<=2*n;i++)
            if(used[i]==1)
                PF("%d\n",i);
    }
    else
        PF("NIE");
}

你可能感兴趣的:(图论,2-SAT)