• [dfs][2-sat] JZOJ P3796 议案决定


    Description

    小C在玩一个游戏,在游戏中他扮演国王的角色。国王手下有M个大臣,他们有一天对国王要处理的N件事务进行投票。每个大臣可以对两件事务进行投票(赞成或反对),格式如下:x c_x y c_y(x, y为整数,c_x, c_y为“Y”(表示赞成)或“N”(表示反对)(不含双引号),表示这个大臣对事务x的态度为c_x,对事务y的态度为c_y)。这些大臣非常难以对付,如果国王的决定和某个大臣的两个意见都不同,那么这个大臣就会离开国王。小C认为不能让任何一个大臣离开国王,否则国王就无法正常地处理自己的事务。请你帮助小C做个决定。
     

    Input

    第一行,两个整数N, M。
    接下来的M行,每行表示一个大臣的投票。

    Output

    如果小C无论如何都只能让至少一个大臣离开国王,则输出“IMPOSSIBLE”(不含双引号),否则输出一个长度为N的字符串,如果第i件事务必须赞成,则第i个字符为“Y”;如果第i件事务必须反对,则第i个字符为“N”,否则第i个字符为“?”。
     

    Sample Input

    3 4
    1 Y 2 N
    1 N 2 N
    1 Y 3 Y
    1 Y 2 Y

    Sample Output

    YN?
     

    Data Constraint

    对于50%的数据,1<=N<=10,1<=M<=40;
    对于全部的数据,1<=N<=1000,1<=M<=4000。

    题解

    • 就是一道2-SAT问题

    • 点u->v代表u发生则v必然发生

    • 每一个条件可以拆为这样的两个条件

    • 如1 Y 2 N  对应的是  1N->2N   2Y->1Y

    • 我们把1Y  1N称为对立节点

    • 那么我们怎么找到将它们连起来且没有对立节点的路径(就是可以找到一条路径,因为对立节点没有边相连)

    • 可以用dfs解决。

    • 如果对某个事务赞成就必须对该事务反对(记为事件A),且对某个事务反对就必须对该事务赞成(记为事件B)

    • 则不可能满足所有条件

    • 否则: 若事件A成立,则对该事务必须反对 

    •            若事件B成立,则对该事务必须赞成

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<memory.h>
     5 using namespace std;
     6 int next[16011],last[16011],head[16011];
     7 int f[16011],k[16022][3],n,m,x,z,num,tot;
     8 bool flag,must[16011][3];
     9 void insert(int x,int y)
    10 {
    11     next[++tot]=head[x];
    12     head[x]=tot;
    13     last[tot]=y;
    14 }
    15 void dfs(int x)
    16 {
    17     if (flag==false) return;
    18     f[x]=num;
    19     if (f[x]==num&&f[x^1]==num) flag=false;
    20     if (flag==false) return;
    21     int i=head[x],j;
    22     while (i!=0)
    23     {
    24         j=last[i];
    25         if (f[j]!=num) dfs(j);
    26         i=next[i];
    27     }
    28     
    29 }
    30 int main()
    31 {
    32     scanf("%d%d",&n,&m);
    33     char ch;
    34     memset(must,true,sizeof(must));
    35     for (int i=1;i<=m;i++)
    36     {
    37         scanf("%d",&x);
    38         while(ch=getchar(),ch!='Y'&&ch!='N');
    39         if (ch=='Y') z=1; else z=0;
    40         if (z==1) k[i][1]=x*2+1; else k[i][1]=x*2;
    41         scanf("%d",&x);
    42         while(ch=getchar(),ch!='Y'&&ch!='N');
    43         if (ch=='Y') z=1; else z=0;
    44         if (z==1) k[i][2]=x*2+1; else k[i][2]=x*2;
    45         insert(k[i][2]^1,k[i][1]);
    46         insert(k[i][1]^1,k[i][2]);
    47     }
    48     for (int i=1;i<=n;i++)
    49     {
    50         flag=true;
    51         num++;
    52         f[2*i]=num;
    53         dfs(2*i);
    54         if (flag==false) must[i][2]=false;
    55         flag=true;
    56         num++;
    57         f[2*i+1]=num;
    58         dfs(2*i+1);
    59         if (flag==false) must[i][1]=false;
    60     }
    61     flag=true;
    62     for (int i=1;i<=n;i++) if (must[i][1]==false&&must[i][2]==false) flag=false;
    63     if (flag==false) printf("IMPOSSIBLE
    ");
    64     else 
    65         for (int i=1;i<=n;i++)
    66         {
    67             if (must[i][2]==true&&must[i][1]==true) printf("?");
    68             if (must[i][2]==false&&must[i][1]==true) printf("Y");
    69             if (must[i][2]==true&&must[i][1]==false) printf("N");
    70         }
    71     return 0;
    72 }
  • 相关阅读:
    python 中 print函数的用法详解
    可转债操作一览
    Python基本数据类型
    python的列表
    理财的方法
    92、Multiple commands produce Info.plist 报错
    91、最新cocoaPods安装与使用
    90、引入头文件不提示
    89、instancetype和id的区别
    88、const、static、extern介绍
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8419407.html
Copyright © 2020-2023  润新知