bzoj2199 奶牛议会【2-sat】

2 篇文章 0 订阅
解题思路

设x,x^1互为反命题,那么对于一张投票(x,y),若不选x则一定选y,不选y一定选x,所以连x^1->y,y^1->x两条边。

连出这个图之后,判断每一个点能不能选。也就是说,判断这个点所有能到达的点是否存在冲突(同一类的Y和N都选了),dfs就可以 。
如果某一个议案的Y和N都不能选,那么IMPOSSIBLE
否则的话,如果某一个点不能选,那么它同类不同项的那个点必须选;否则的话这两个点选不选都行。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<ctime>
#include<vector>
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=2005;
int n,m;
bool visit[N],ok[N];
vector<int>g[N];

int p(int x,char c)
{
    return c=='Y'?x-1<<1:(x-1<<1)+1;
}

void dfs(int u)
{
    visit[u]=true;
    for(int e=0;e<g[u].size();e++)
    {
        int v=g[u][e];
        if(!visit[v])dfs(v);
    }
}

int main()
{
    //freopen("lx.in","r",stdin);
    int x,y;
    char c1,c2;
    n=getint(),m=getint();
    while(m--)
    {
        x=getint();
        for(c1=getchar();c1!='Y'&&c1!='N';c1=getchar());
        y=getint();
        for(c2=getchar();c2!='Y'&&c2!='N';c2=getchar());
        x=p(x,c1),y=p(y,c2);
        g[x^1].push_back(y);
        g[y^1].push_back(x);
    }

    memset(ok,true,sizeof(ok));
    for(int i=0;i<2*n;i++)
    {
        memset(visit,false,sizeof(visit));
        dfs(i); 
        for(int j=0;j<2*n;j++)
            if(visit[j]&&visit[j^1])
            {
                ok[i]=false;
                break;
            }
        if(!ok[i]&&!ok[i^1])
        {
            cout<<"IMPOSSIBLE";
            return 0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(!ok[p(i,'Y')])cout<<"N";
        else if(!ok[p(i,'N')])cout<<"Y";
        else cout<<"?";
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值