[HDU1814]Peaceful Commission(2-SAT)

来源:互联网 发布:java soa架构案例 编辑:程序博客网 时间:2024/06/05 20:53

题目描述

传送门

题解

经典的2-SAT问题,要求输出字典序最小的解
首先贪心地选最小的,每一次选择将其影响的点都修改,然后判断是否合法

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 40005int n,m,x,y,top;int tot,point[N],nxt[N],v[N];int stack[N],flag[N],ans[N];bool can,is_end;void clear(){    x=y=tot=can=is_end=0;    memset(point,0,sizeof(point));memset(nxt,0,sizeof(nxt));memset(v,0,sizeof(v));    memset(flag,0,sizeof(flag));memset(ans,0,sizeof(ans));}void add(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x){    if (flag[x]==-1) {can=false;return;}    if (flag[x]) return;    flag[x]=1;flag[((x-1)^1)+1]=-1;    stack[++top]=x;    for (int i=point[x];i&&can;i=nxt[i])    {        if (!flag[v[i]]) dfs(v[i]);        else if (flag[v[i]]==-1) can=false;    }}int main(){    while (~scanf("%d%d",&n,&m))    {        clear();        for (int i=1;i<=m;++i)        {            scanf("%d%d",&x,&y);            add(x,((y-1)^1)+1);            add(y,((x-1)^1)+1);        }        for (int i=1;i<=2*n;i+=2)        {            if (flag[i]&&flag[i+1])            {                if (flag[i]==flag[i+1]) {is_end=true;break;}                if (flag[i]==1) ans[i/2+1]=i;                else ans[i/2+1]=i+1;                continue;            }            top=0;            can=true;dfs(i);            if (can) {ans[i/2+1]=i;continue;}            else                for (int j=1;j<=top;++j)                    flag[stack[j]]=flag[((stack[j]-1)^1)+1]=0;            top=0;            can=true;dfs(i+1);            if (can) {ans[i/2+1]=i+1;continue;}            else                for (int j=1;j<=top;++j)                    flag[stack[j]]=flag[((stack[j]-1)^1)+1]=0;            is_end=true;break;        }        if (is_end) {puts("NIE");continue;}        for (int i=1;i<=n;++i) printf("%d\n",ans[i]);    }}
0 0