【BZOJ】2199奶牛议会-2-SAT

传送门:bzoj2199
权限题? 没关系,你洛上也有:洛谷- [USACO11JAN]大陆议会The Continental Cowngress


题解

一道2-SAT简单题。
只需要用到2-SAT连有向边的操作,拓扑排序和缩点都不需要,直接暴力找(非常之暴力)。


代码

#include<bits/stdc++.h>
using namespace std;

const int M=4e3+10,N=1e3+10;
int head[N<<1],to[M<<1],nxt[M<<1];
int x,y,n,m,cur,tot,ans[N],mark[N<<1]; 
char A,B;

inline int rd()
{
   char ch=getchar();int x=0,f=1;
   while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
   while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}    
   return x*f;
}

inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}

inline void dfs(int x)
{
    mark[x]=cur;
    for(int i=head[x];i;i=nxt[i])
        if(mark[to[i]]!=cur) dfs(to[i]);
}

inline int check(int x)
{
    ++cur;
    dfs(x);
    for(int i=1;i<=n;i++){
        if(mark[i<<1]==cur && mark[i<<1|1]==cur)
         return false;
    }
    return true;
}

int main(){
    n=rd(),m=rd();
    for(int i=1;i<=m;i++){
       x=rd()<<1;cin>>A;y=rd()<<1;cin>>B;
       if(A=='N') x++;if(B=='N') y++;
       lk(x^1,y);lk(y^1,x); 
    }
    for(int i=1;i<=n;i++){
        x=check(i<<1),y=check(i<<1|1);
        if(!x && !y){
            printf("IMPOSSIBLE\n");return 0;
        }
        if(x) ans[i]= y? 2:0;else ans[i]=1;
    }
    for(int i=1;i<=n;i++){
        switch(ans[i]){
            case(0):putchar('Y');break;
            case(1):putchar('N');break;
            case(2):putchar('?');break;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80303609