hdu 4115 2-SAT


  1 /*
2 题解:2-SAT
3 一开始每一个round都有两种状态可选,并且选了每种状态有后面的限制其中一种选后另一状态的状态也被固定,
4 十分符合2-SAT的用法;
5 */
6 #include <cstdio>
7 #include <cstring>
8 #include <iostream>
9 #include <vector>
10 #include <queue>
11
12 #define clr(a,b) (memset(a,b,sizeof(a)))
13 #define cpy(a,b) (memcpy(a,b,sizeof(b)))
14
15 using namespace std;
16
17 const int NV = 20005; // 点数要注意,后面是有两个点集
18 const int NE = 200005; // 边也要注意加边的数量不只是限制条件的数目,因为一个限制条件可能要加几条边
19 const int W = 0;
20 const int R = 1;
21 const int B = 2;
22
23 int opp[NV];
24 int in[NV];
25 bool ans[NV];
26 int col[NV];
27 int n, nn, m;
28 inline int Min(int a, int b) {return a < b ? a : b;}
29 struct SCC {
30 int deep,scc, top, SZ, n;
31 struct edge {int v, next;} E[NE];
32 int pre[NV], dep[NV], low[NV], id[NV], st[NV];
33 bool in[NV];
34 inline void init(int _n) {
35 n = _n;
36 clr(pre, -1);
37 clr(dep, -1);
38 clr(in,false);
39 deep = scc = SZ = top = 0;
40 }
41 void tarjan(int u) {
42 int v, i;
43 dep[u] = low[u] = ++ deep;
44 st[top++] = u;
45
46 in[u] = true;
47 for (i = pre[u]; i != -1; i = E[i].next) {
48 v = E[i].v;
49 if (dep[v] == -1) {
50 tarjan(v);
51 low[u] = Min(low[u], low[v]);
52 }
53 else if (in[v]) {
54 low[u] = Min(low[u], dep[v]);
55 }
56 }
57 if (low[u] == dep[u]) {
58 do {
59 v = st[--top];
60 in[v] = false;
61 id[v] = scc;
62 } while (u != v);
63 scc ++;
64 }
65 }
66 inline void insert(int u, int v) {
67 E[SZ].v = v;
68 E[SZ].next = pre[u];
69 pre[u] = SZ ++;
70 }
71 inline void solve() {
72 for (int i = 0; i < n; i++) {
73 if (dep[i] == -1) {
74 tarjan(i);
75 }
76 }
77 }
78 } G;
79 int main(void) {
80 int i, j;
81 int x, y;
82 int t;
83 int alice[20005];
84 scanf("%d",&t);
85 for(int cas=1; cas<=t; cas++)
86 {
87 int n,m;
88 scanf("%d%d", &n, &m);
89 nn = n * 2; // 正反两个点集
90 for (i = 0; i < nn; i++)
91 opp[i] = (i ^ 1);
92
93 G.init(nn);
94 for(int i=0; i<nn; i+=2)
95 {
96 int cc;
97 scanf("%d",&cc);
98 switch(cc)
99 {
100 case 1: alice[i] = 1,alice[opp[i]] = 2; break;
101 case 2: alice[i] = 2,alice[opp[i]] = 3; break;
102 case 3: alice[i] = 3,alice[opp[i]] = 1; break;
103 }
104 }
105 for (i = 0; i < m; i++) {
106 int a, b, k;
107 scanf("%d%d%d", &a, &b, &k);
108 a--;
109 a*=2;
110 b--;
111 b*=2;
112 /*
113 此处加边要注意是从0开始,而且偶数为该点集,奇数为对立点集
114 G.insert(x, opp[y]);
115 G.insert(y, opp[x]);
116 */
117 if (k)
118 {
119 if (alice[a] == alice[b]) // 相等说明a必然要退出opp[b]才能得到正确结果,反过来亦然
120 {
121 G.insert(a,opp[b]);
122 G.insert(b,opp[a]);
123 }
124 if (alice[a] == alice[opp[b]])
125 {
126 G.insert(a,b);
127 G.insert(opp[b],opp[a]);
128 }
129 if (alice[opp[a]] == alice[b])
130 {
131 G.insert(opp[a],opp[b]);
132 G.insert(b,a);
133 }
134 if (alice[opp[a]] == alice[opp[b]])
135 {
136 G.insert(opp[a],b);
137 G.insert(opp[b],a);
138 }
139 }
140 else
141 {
142 if (alice[a] != alice[b])
143 {
144 G.insert(a,opp[b]);
145 G.insert(b,opp[a]);
146 }
147 if (alice[a] != alice[opp[b]])
148 {
149 G.insert(a,b);
150 G.insert(opp[b],opp[a]);
151 }
152 if (alice[opp[a]] != alice[b])
153 {
154 G.insert(opp[a],opp[b]);
155 G.insert(b,a);
156 }
157 if (alice[opp[a]] != alice[opp[b]])
158 {
159 G.insert(opp[a],b);
160 G.insert(opp[b],a);
161 }
162 }
163 }
164 G.solve();
165 for (i = 0; i < nn; i += 2) {
166 if (G.id[i] == G.id[opp[i]]) {
167 break;
168 }
169 }
170 if (i < nn) { // 不存在
171 printf("Case #%d: no\n",cas);
172 }
173 else
174 printf("Case #%d: yes\n",cas);
175 }
176 return 0;
177 }

hdu 4115 2-SAT

时间: 2024-10-10 08:50:18

hdu 4115 2-SAT的相关文章

hdu 4115 Eliminate the Conflict

Description Conflicts are everywhere in the world, from the young to the elderly, from families to countries. Conflicts cause quarrels, fights or even wars. How wonderful the world will be if all conflicts can be eliminated.Edward contributes his lif

hdu 3715 hdu 1816 hdu 4115 (2-sat)

三个2-sat问题,我总结一下自己的经验,我还是太菜,好久没做2-sat,又不太会建图了 总结:2-sat问题的核心就是建模 建模的思想很重要: 1.首先要怎么才能看出来是2-sat问题,对于每一个点,都有两种选择,则可以考虑是2-sat 比如让你在n组里面选n个,每组2个东西,这样就是2-sat的模型 2.确定是2-sat问题之后,就是要确定,拥有两种选择的对象,比如下面的例题里,有的是x[i]的取值有0或者1两种,有的是一串钥匙有两个,但你只能选择其中一个,则对于一个钥匙,它的取值有取或者不

HDU 4115 Eliminate the Conflict(2-sat)

HDU 4115 Eliminate the Conflict 题目链接 题意:Alice和Bob这对狗男女在玩剪刀石头布,已知Bob每轮要出什么,然后Bob给Alice一些限制,1表示i轮和j轮Alice必须出不一样的,0表示必须出一样的,如果Alice有一局输了就算输了,否则就是赢,问Alice是否能赢 思路:2-sat问题,已经Bob出什么,Alice要么就出赢的要么就出平的,然后加上m个约束就是2-sat问题了 代码: #include <cstdio> #include <cs

HDU 4115 Eliminate the Conflict【2-sat】

转载请注明出处:http://blog.csdn.net/u013912596 题目大意: Alice和Bob玩若干轮石头剪刀布的游戏,Alice已经知道了Bob在每一轮会出什么,但是Bob会给出一些Alice的限制条件,问Alice在不打破这些限制的情况下,有没有可能赢. 限制格式为(i,j,w),i,j代表第几轮,w=1的话,要求Alice在第i轮和第j轮的策略不能相同,w=0的话,要求Alice在第i轮和第j轮的策略必须相同. 思路: 刚开始以为这个题是个DP,按照这个想了一下,发现要求相

hdu 4115 石头剪子布(2-sat问题)

/* 题意:石头剪子布,现在已知n回合bob将会出什么,对alice有限制,对于u,v,w:如果w=0说明a,b回合必须出的一样 否则,必须不一样.alice如果输一回合就输了,否则就赢了 解: 2-sat alice有两个选择要么平手要么赢. 对于第u回合,alice可以出au,bu: 对于第v回合,alice可以出av,bv: 当w=0那么第u回合和第v回合必须相同 比较au和bu.bv是否矛盾,如果矛盾建两条边 比较av和bu.bv是否矛盾,如果矛盾建两条边 当w=1第u回合和第v回合必须

HDU 4115 Eliminate the Conflict (2011年成都赛区现场赛E题)

1.题目描述:点击打开链接 2.解题思路:本题属于2-SAT问题,第一次做这种题,还是很感兴趣的.2-SAT解决的是给定m条语句,每一条语句形如"xi为真或xj为假",问你是否可能让所有的语句都成立.那么不难发现,本题就属于一种2-SAT问题. 首先,根据题意可知,第i轮有2种出法,要么是x[i],要么是(x[i]+1)%3.我们令xi为真表示出x[i],xi为假表示出(x[i]+1)%3.对于w==1的情况,我们要分2种情况讨论:当x[u]==x[v]时,表示第u轮出x[u],那么第

HDU 4115 Eliminate the Conflict(2-sat 判解存在性)

题意: 有两个人玩一个石头剪刀布的游戏,两个人连续玩N轮,给出其中一个人的N轮出的情况和该人对另外一个人的一些限制条件,有两种限制:每种限制表示为:(a,b,c) ,如果c==0 则表示该人对另外一个人的限制为第a局和第b局出的应该一样,如果c==1表示不一样,问另外一个人是否有赢(规定每轮都不输就称赢)的可能. 思路:所以可以推出每轮必须出能平或赢的动作(两种选择)所以是2-sat.再找到约束关系即可 #include<cstdio> #include<iostream> #in

Eliminate the Conflict HDU - 4115

Conflicts are everywhere in the world, from the young to the elderly, from families to countries. Conflicts cause quarrels, fights or even wars. How wonderful the world will be if all conflicts can be eliminated. Edward contributes his lifetime to in

2-SAT问题

2-SAT问题 现有一个由N个布尔值组成的序列A,给出一些限制关系,比如A[x]AND A[y]=0.A[x] OR A[y] OR A[z]=1等,要确定A[0..N-1]的值,使得其满足所有限制关系.这个称为SAT问题,特别的,若每种限制关系中最多只对两个元素进行限制,则称为2-SAT问题. 由于在2-SAT问题中,最多只对两个元素进行限制,所以可能的限制关系共有11种: A[x] NOT A[x] A[x] AND A[y] A[x] AND NOT A[y] A[x] OR A[y] A