HDU 1814 Two_Sat

来源:互联网 发布:华侨大学怎么样知乎 编辑:程序博客网 时间:2024/05/21 08:51


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1814

题意: 有(1,2),(3,4), ...(2n-1,2n),n对数,要在每对中选出一个共n个,并且满足m个约束条件,条件(a,b)表示ab不能同时被选,按字典序输出答案,无解输出NIE


分析: Two_Sat问题,假设A,A‘为一对,B,B'为一对,那么对于约束条件(A,B),在选A的时候必须选B’,选B的时候必选选A‘,加边A->B',B->A'

模板用的是大白书上的,跑出来直接是字典序,mark为true即为取当前值。




#include <iostream>#include<cstdio>#include<algorithm>#include<string>#include<cstring>#include<vector>#define maxn 8005using namespace std;struct TwoSAT{    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 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;    }    void print(){        if(!solve())        printf("NIE\n");        else {            for(int i=0;i<n;i++){                if(mark[i*2])                printf("%d\n",i*2+1);                else                printf("%d\n",i*2+2);            }        }    }};int main(){    int n,m,x,y;    while(~scanf("%d%d",&n,&m)){        TwoSAT T;        T.init(n);        while(m--){            scanf("%d%d",&x,&y);            T.add_clause(x-1,y-1);        }        T.print();    }    return 0;}


0 0