奶牛议会

题目link:https://www.luogu.com.cn/problem/P3007

$2-SAT$ 裸题。

建图,设第 $i$ 号点表示支持第 $i$ 个法案,第 $i$ $+$ $n$ 号点表示反对第 $i$ 个法案。

对于每头奶牛的两个条件,因为题目要求必须满足其一,那就对奶牛的两个条件之一取反,并向另一个条件连边,表示如果不满足奶牛的其中一个要求,那必须满足另一个要求。

跑一遍 $Tarjan$ ,然后判断 $i$ 号点, $i$ $+$ $n$ 号点是否在同一个强连通分量里,如果是的话无论反对还是支持第 $i$ 个法案都会矛盾,无解。

之后如果有解的话(不满足上一行的情况),那么 $O(n$2$)$暴力判断如果支持了第 $i$ 号法案会不会矛盾,反对会不会矛盾,按情况输出。

code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 stack < int > pru;
 5 int n, m, head[2010], low[2010], dfn[2010], col[2010], vis[2010], num, z, color; char s1[10], s2[10];
 6 struct node {int next, to;}stu[8010];
 7 void add(int x, int y) {stu[++num].next = head[x]; stu[num].to = y; head[x] = num;}
 8 void tarjan(int u)
 9 {
10     dfn[u] = low[u] = ++z; pru.push(u);
11     for(int i = head[u]; i; i = stu[i].next)
12     {
13         int k = stu[i].to;
14         if(!dfn[k]) tarjan(k), low[u] = min(low[u], low[k]);
15         else if(!col[k]) low[u] = min(low[u], dfn[k]);
16     }
17     if(low[u] == dfn[u])
18     {
19         col[u] = ++color;
20         while(pru.top() != u)
21             col[pru.top()] = color, pru.pop();
22         pru.pop();
23     }
24     return;
25 }
26 void dfs(int u)
27 {
28     vis[u] = 1;
29     for(int i = head[u]; i; i = stu[i].next)
30     {
31         int k = stu[i].to;
32         if(!vis[k]) dfs(k);
33     }
34     return;
35 }
36 int check(int x)
37 {
38     memset(vis, 0, sizeof(vis)); dfs(x);
39     for(int i = 1; i <= n; ++i)
40         if(vis[i] && vis[i + n]) return 0;
41     return 1;
42 }
43 int main()
44 {
45     scanf("%d %d", &n, &m);
46     for(int i = 1, x, y, a, b; i <= m; ++i)
47     {
48         scanf("%d %s %d %s", &x, s1, &y, s2);
49         a = (s1[0] == 'Y'), b = (s2[0] == 'Y');
50         add(a * n + x, !b * n + y), add(b * n + y, !a * n + x);
51     }
52     for(int i = 1; i <= 2 * n; ++i)
53         if(!dfn[i]) tarjan(i);
54     for(int i = 1; i <= n; ++i)
55         if(col[i] == col[i + n]) {puts("IMPOSSIBLE"); return 0;}
56     for(int i = 1, Tr, Fa; i <= n; ++i)
57     {
58         Tr = check(i), Fa = check(i + n);
59         if(Tr && Fa) putchar('?'); else if(Tr) putchar('Y'); else putchar('N');
60     }
61     return 0;
62 }

 

 

posted @ 2021-02-21 21:41  louis_11  阅读(142)  评论(0编辑  收藏  举报