BZOJ 2199: [Usaco2011 Jan]奶牛议会 2- SAT

2024-03-19 04:10

本文主要是介绍BZOJ 2199: [Usaco2011 Jan]奶牛议会 2- SAT,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2199: [Usaco2011 Jan]奶牛议会

Description

由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会。议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 <= M <= 4000) 会给N个议案投票(1 <= N <= 1,000) 。每只 奶牛会对恰好两个议案 B_i and C_i (1 <= B_i <= N; 1 <= C_i <= N)投 出“是”或“否”(输入文件中的'Y'和'N')。他们的投票结果分别为VB_i (VB_i in {'Y', 'N'}) and VC_i (VC_i in {'Y', 'N'})。 最后,议案会以如下的方式决定:每只奶牛投出的两票中至少有一票和最终结果相符合。 例如Bessie给议案1投了赞成'Y',给议案2投了反对'N',那么在任何合法的议案通过 方案中,必须满足议案1必须是'Y'或者议案2必须是'N'(或者同时满足)。 给出每只奶牛的投票,你的工作是确定哪些议案可以通过,哪些不能。如果不存在这样一个方案, 输出"IMPOSSIBLE"。如果至少有一个解,输出: Y 如果在每个解中,这个议案都必须通过 N 如果在每个解中,这个议案都必须驳回 ? 如果有的解这个议案可以通过,有的解中这个议案会被驳回 考虑如下的投票集合: - - - - - 议案 - - - - - 1 2 3 奶牛 1 YES NO 奶牛 2 NO NO 奶牛 3 YES YES 奶牛 4 YES YES 下面是两个可能的解: * 议案 1 通过(满足奶牛1,3,4) * 议案 2 驳回(满足奶牛2) * 议案 3 可以通过也可以驳回(这就是有两个解的原因) 事实上,上面的问题也只有两个解。所以,输出的答案如下: YN?

Input

* 第1行:两个空格隔开的整数:N和M * 第2到M+1行:第i+1行描述第i只奶牛的投票方案:B_i, VB_i, C_i, VC_i

Output

* 第1行:一个含有N个字符的串,第i个字符要么是'Y'(第i个议案必须通过),或者是'N' (第i个议案必须驳回),或者是'?'。 如果无解,输出"IMPOSSIBLE"。

Sample Input


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


Sample Output

YN?

思路:

  2-SAT 裸题, 对于每个要求, 我们把非x和y , 非y和x 连一条边,然后枚举每个点的两种情况进行bfs染色,由连边可知,bfs染色后会满足所有情况,若某个点既选又不选,则这种情况不可能。近似暴力的一道题。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 5000, M = 10000;
int head[N], to[M], nxt[M], _; 
char ans[N];
bool vis[N];
void add(int a,int b) {to[++_] = b;nxt[_]  = head[a];head[a] = _;
}
int n, m;
queue<int>q;
bool bfs(int s) {memset(vis, 0, sizeof(vis));vis[s] = 1;while(!q.empty())q.pop();q.push(s);while(!q.empty()) {int u = q.front();q.pop();for(int i=head[u];i;i=nxt[i]) {if(!vis[to[i]]) {vis[to[i]] = 1;q.push(to[i]);}}}for(int i=1;i<=n;i++) {if(vis[i]&&vis[n+i]) return 0;}return 1;
}
int main() {scanf("%d%d", &n, &m);char s1[3], s2[3];for(int i=1, x, y;i<=m;i++) {scanf("%d%s%d%s", &x, s1, &y, s2);int tx, ty;if(s1[0]=='Y') tx = 1;else tx = 0;if(s2[0]=='Y') ty = 1;else ty = 0;add((1-tx)*n+x,ty*n+y);add((1-ty)*n+y,tx*n+x);}for(int i=1;i<=n;i++) {int t = bfs(i+n), f = bfs(i);if(!t&&!f) {puts("IMPOSSIBLE");return 0;}if(t&&f) ans[i] = '?';else if(!f) ans[i] = 'Y';else if(!t) ans[i] = 'N';}for(int i=1;i<=n;i++) {putchar(ans[i]);}
}
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 5000, M = 10000;
int head[N], to[M], nxt[M], _; 
char ans[N];
bool vis[N];
void add(int a,int b) {to[++_] = b;nxt[_]  = head[a];head[a] = _;
}
int n, m;
queue<int>q;
bool bfs(int s) {memset(vis, 0, sizeof(vis));vis[s] = 1;while(!q.empty())q.pop();q.push(s);while(!q.empty()) {int u = q.front();q.pop();for(int i=head[u];i;i=nxt[i]) {if(!vis[to[i]]) {vis[to[i]] = 1;q.push(to[i]);}}}for(int i=1;i<=n;i++) {if(vis[i]&&vis[n+i]) return 0;}return 1;
}
int main() {scanf("%d%d", &n, &m);char s1[3], s2[3];for(int i=1, x, y;i<=m;i++) {scanf("%d%s%d%s", &x, s1, &y, s2);int tx, ty;if(s1[0]=='Y') tx = 1;else tx = 0;if(s2[0]=='Y') ty = 1;else ty = 0;add((1-tx)*n+x,ty*n+y);add((1-ty)*n+y,tx*n+x);}for(int i=1;i<=n;i++) {int t = bfs(i+n), f = bfs(i);if(!t&&!f) {puts("IMPOSSIBLE");return 0;}if(t&&f) ans[i] = '?';else if(!f) ans[i] = 'Y';else if(!t) ans[i] = 'N';}for(int i=1;i<=n;i++) {putchar(ans[i]);}
}
View Code

 

转载于:https://www.cnblogs.com/Tobichi/p/9204472.html

这篇关于BZOJ 2199: [Usaco2011 Jan]奶牛议会 2- SAT的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/824746

相关文章

【BZOJ】1324 Exca王者之剑 最大权独立集

传送门:【BZOJ】1324  Exca王者之剑 题目分析:赤裸裸的最大权独立集。。。最小割解决 代码如下: #include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int

【BZOJ】1026: [SCOI2009]windy数 数位DP

传送门:【BZOJ】1026: [SCOI2009]windy数 题目分析:数位DP水题。 代码如下: #include <stdio.h>#include <cstring>#include <algorithm>#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )#define For( i ,

【BZOJ】2152: 聪聪可可 点分治

传送门:【BZOJ】2152: 聪聪可可 题目分析:记录权值和%3的路径的个数。。。然后去重。。没了。。 代码如下: #include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std ;typedef lo

BZOJ 2440 2301 莫比乌斯应用

http://www.lydsy.com/JudgeOnline/problem.php?id=2440 Description 小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些 数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而 这丝毫不影响他对其他数的热爱。  这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一 个小X讨厌

BZOJ 3732: Network(最小生成树+倍增)

题目链接 题意:给出一个图,每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少 很明显最终查询的边一定是在最小生成树里面的,先跑出最小生成树,然后,可以树链剖分,也可以使用倍增来计算 #include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define

新SAT官方范文得分的分段分析

· 本次官方给出了两道写作新样题,样题的材料文章分别是节选自Paul Bogard于2012.12.21发表在《洛杉矶时报》的“Let There Be Dark.”及Dana Gioia于2005.04.10发表在《纽约时报》的“Why Literature Matters” 。   · 张卉老师结合之前的新SAT改革的说明,认为写作部分的基本出题思路没有大的调整,样题的材料文章都是节选自

SAT改革:SAT官方最新样题解读与备考建议

College Board于2015年1月9日释放新SAT考试最新样题,小编第一时间为各位考生及家长进行新SAT考试的样题解析及备考规划建议,此次小编给出了SAT语法样题一、样题二,阅读第一、二篇,数学,写作样题与范文的详细解读,希望各位考生在2015冲刺高分成绩! 新SAT科目官方样题答案解析新SAT语法新SAT写作与语法能力真题及答案样题1解析 | 样题2解析 | 新SAT语法备考建议新

SAT阅读考试的典型问题及应对策略

SAT阅读部分的测试时间为70分钟,共65道选择题,每道选择题有五项选择,其中只有一项选择为正确答案。结合所阅读的文章,每道选择题以提出问题的形式出现,通常被问到的问题类型为:本篇文章的主要观点及中心主题;在本篇文章中,作者对所论述问题的态度及基本观点;判断所阅读文章的体裁形式,例如:议论、寓言、科技、历史、讽刺、悲剧、喜剧、浪漫、科幻、恐怖、写实及诗歌;作者在文章中所用的修辞手法的目的,在这

如何克服SAT考试阅读难关?

对中国考生而言,SAT阅读部分的考题为最难。SAT阅读由两部分组成,即阅读判断及句子填空,全部为选择题型。SAT阅读的考试时间为70分钟,65道题,每答对一道题得12.3分,总共800分。国内考生若想在SAT阅读中取得理想的成绩,至少要具备两项基本能力,其一,要掌握一万左右的英语词汇量;其二,要有能力根据上下文的关系,准确识别不认识的英语词汇。SAT阅读部分题量大、时间紧,考生要在不超过一分钟

四步走循序渐进克服SAT阅读关

五月份的SAT考试刚刚结束,阅读自然是各个部分中最有难度的,也是最令同学们望而生畏的。但相较于几个月前,同学们纷纷表示,在经过了系统而全面的训练和练习之后,还是可以打倒阅读这一SAT高分路上拦路虎的。 事实上,只要过了四个关卡,同学们就可彻底解决SAT阅读。   第一关:单词关   要读懂一篇文章,无疑最基本的一点是要认识这篇文章的字。如果入目皆是生词,一定会有一种“满纸荒唐言”的感觉――