hdu 1814(2sat)

题意: 有n个组织,每个组织有两个人,第i组的两个人分别是2*i-1,2*i,其中有m对人相互讨厌,要在n个组织中各选一个人,使得没有任何两个人相互讨厌,如果存在答案,输出字典序最小的,如果无解,输出NIE

分析:如果i和j相互讨厌,那么那么如果选i,那么必定选j^1,选i^1必定选j,加入这两条边,跑2sat,字典序,用从小到大枚举来保证,如果找到一个解,立刻退出

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;

struct sat{
    int n;
    vector<int>G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;

    bool dfs(int x){
        if (mark[x^1]) return false;
        if (mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for (int i=0;i<G[x].size();i++)
            if (!dfs(G[x][i])) return false;
        return true;
    }

    void init(int n){
        this->n=n;
        for (int i=0;i<n*2;i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }

    void add_clause(int x,int xval,int y,int yval){
        x=x*2+xval;
        y=y*2+yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }

    void add(int x,int y){
        G[x].push_back(y^1);
        G[y].push_back(x^1);
    }

    bool solve(){
        for (int i=0;i<n*2;i+=2)
            if (!mark[i]&&!mark[i+1]){
                c=0;
                if (!dfs(i)){
                    while (c>0) mark[S[--c]]=false;
                    if (!dfs(i+1)) return false;
                }
            }
        return true;
    }
}Sat;

int main(){
    int n,m;
    while(cin>>n>>m){
        Sat.init(n);
        for(int i=0;i<m;i++){
            int a,b;
            cin>>a>>b;
            a--;b--;
            //a=a>>1;b=b>>1;
            //Sat.add_clause(a,(a&1),b,(b&1));
            Sat.add(a,b);
        }
        if(Sat.solve()){
            for(int i=0;i<2*n;i+=2)
                if(Sat.mark[i])
                    cout<<i+1<<endl;
                else
                    cout<<i+2<<endl;
        }
        else puts("NIE");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/jihe/p/6433695.html