jzoj P3796 议案决定___2-SAT

题目大意:

国王手下有M个大臣,他们有一天对国王要处理的N件事务进行投票。每个大臣可以对两件事务赞成或反对,格式如下:x c_x y c_y表示这个大臣对事务x的态度为c_x,对事务y的态度为c_y。如果国王的决定和某个大臣的两个意见都不同,那么这个大臣就会离开国王。小C认为不能让任何一个大臣离开国王,否则国王就无法正常地处理自己的事务。请你帮助小C做个决定。
如果小C无论如何都只能让至少一个大臣离开国王,则输出“IMPOSSIBLE”(不含双引号),否则输出一个长度为N的字符串,如果第i件事务必须赞成,则第i个字符为“Y”;如果第i件事务必须反对,则第i个字符为“N”,否则第i个字符为“?”。

x, y为整数,c_x, c_y为“Y”(表示赞成)或“N”(表示反对)
对于50%的数据,1<=N<=10,1<=M<=40;
对于全部的数据,1<=N<=1000,1<=M<=4000。

题解:

这题一开始并没有什么想法,各种暴力都套不进。。。
后来看了几篇博客,才知道其实很简单
对于一对[x,cx,y,cy]而言,你要使得大臣不离开至少要有一个满足
则,
举例一种情况:
1 Y 2 Y
这时候,你要留下大臣,就要满足1 Y 或者 2 Y
我们可以这样理解
对1是N时对2必定要是Y
对2是N时对1必定要是Y
这时候其他的同理
我们就可以将这些关系建成一条条边

然后枚举每一个事务的Y/N 两种状态,沿着边跑,
判断是否当你对i持Y意见时,你是否必定必须要对i持N意见!
就是你i选了Y以后那些边对应的意见就要相对应的做出选择,看这些选择时候能使得事务i必定出现N
你对i持N意见时,同理
但2个意见都没冲突时,输出?
Y没N有,输出Y
N没Y有,输出N
都有冲突,哇!IMPOSSIBLE
这或许就是传说中的2-SAT

代码:

const
        maxn=4001;

var
        a:array[0..maxn,1..2] of longint;
        go,next:array [0..2*maxn] of longint;
        cp,list:array [0..2001] of longint;
        n,m,i,j,rp,p,q:longint;
        check,rp1,rp2:boolean;
        ans:ansistring;
        x1,x2:char;

procedure add(x,y:longint);
begin
        inc(p);
        go[p]:=y;
        next[p]:=list[x];
        list[x]:=p;
end;

procedure work(x:longint);
var
        i:longint;
begin
        if not(rp1) then exit;
        if x=rp then
           begin
                rp1:=false;
                exit;
           end;
        cp[x]:=q;
        i:=list[x];
        while i>0 do
        begin
             if cp[go[i]]<>q then work(go[i]);
             if not(rp1) then exit;
             i:=next[i];
        end;
end;
begin
         readln(n,m);
         for i:=1 to m do
           begin
               readln(a[i,1],x1,x1,a[i,2],x2,x2);
               if (x1='Y') and (x2='N') then
                 begin
                     add(a[i,1]+n,a[i,2]+n);
                     add(a[i,2],a[i,1]);
                 end;
               if (x1='Y') and (x2='Y') then
                 begin
                     add(a[i,1]+n,a[i,2]);
                     add(a[i,2]+n,a[i,1]);
                 end;
               if (x1='N') and (x2='Y') then
                 begin
                     add(a[i,1],a[i,2]);
                     add(a[i,2]+n,a[i,1]+n);
                 end;
               if (x1='N') and (x2='N') then
                 begin
                     add(a[i,1],a[i,2]+n);
                     add(a[i,2],a[i,1]+n);
                 end;
           end;

         fillchar(cp,sizeof(cp),0);
         ans:='';
         q:=0;

         for i:=1 to n do
            begin
                   inc(q);
                   rp1:=true;
                   rp:=n+i;
                   work(i);
                   rp2:=rp1;

                   inc(q);
                   rp1:=true;
                   rp:=i;
                   work(n+i);

                   if not(rp1) and not(rp2)
                      then begin
                                  writeln('IMPOSSIBLE');
                                  halt;
                           end;

                   if (rp1) and (rp2) then ans:=ans+'?'
                                      else if rp2 then ans:=ans+'Y'
                                                  else ans:=ans+'N';
            end;
         writeln(ans);
end.
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值