[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 }
原文地址:https://www.cnblogs.com/Comfortable/p/8419407.html