uva 1086 - The Ministers' Major Mess(2 SAT)
2015-09-10 22:53
197 查看
题目链接:uva 1086 - The Ministers' Major Mess
枚举每个点,判断是否y,n都存在解,如果都存在即为?, 最后做一遍2SAT即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 105;
struct TwoSAT {
int n, S[maxn * 2], C;
bool mark[maxn * 2], must[maxn * 2];
vector<int> G[maxn * 2];
void init (int n) {
this->n = n;
memset(must, 0, sizeof(must));
for (int i = 0; i < n*2; i++) G[i].clear();
}
void clear() { memcpy(mark, must, sizeof(must)); }
void addClause(int x, int xflag, int y, int yflag) {
x = x * 2 + xflag;
y = y * 2 + yflag;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
void draw(int u) {
must[u] = true;
for (int i = 0; i < G[u].size(); i++)
if (!must[G[u][i]]) draw(G[u][i]);
}
bool dfs (int u) {
if (mark[u^1]) return false;
if (mark[u]) return true;
mark[u] = true;
S[C++] = u;
for (int i = 0; i < G[u].size(); i++)
if (!dfs(G[u][i])) return false;
return true;
}
bool solve () {
for (int i = 0; i < 2*n; i += 2) {
if (mark[i] && mark[i+1]) return false;
if (!mark[i] && !mark[i+1]) {
C = 0;
if (!dfs(i)) {
while (C) mark[S[--C]] = false;
if (!dfs(i+1)) return false;
}
}
}
return true;
}
}solver;
int N, M, T[maxn];
void init () {
int k, x[10], y[10];
char s[10];
solver.init(N);
memset(T, 0, sizeof(T));
while (M--) {
scanf("%d", &k);
for (int i = 0; i < k; i++) {
scanf("%d%s", &x[i], s);
x[i]--; y[i] = s[0] == 'y' ? 0 : 1;
}
if (k >= 3) {
for (int i = 0; i < k; i++)
for (int j = i + 1; j < k; j++)
solver.addClause(x[i], y[i], x[j], y[j]);
} else {
for (int i = 0; i < k; i++)
solver.must[x[i]*2+y[i]] = true;
}
}
}
int main () {
int cas = 1;
while (scanf("%d%d", &N, &M) == 2 && N + M) {
init();
for (int i = 0; i < 2*N; i++)
if (solver.must[i]) solver.draw(i);
for (int i = 0; i < 2*N; i += 2) {
if (solver.must[i] || solver.must[i+1]) continue;
solver.clear();
solver.mark[i] = true;
bool flag1 = solver.solve();
solver.clear();
solver.mark[i+1] = true;
bool flag2 = solver.solve();
if (flag1 && flag2) T[i/2] = 1;
}
solver.clear();
printf("Case %d: ", cas++);
if (!solver.solve()) printf("impossible\n");
else {
for (int i = 0; i < N; i++) {
if (T[i]) printf("?");
else if (solver.mark[i*2]) printf("y");
else printf("n");
}
printf("\n");
}
}
return 0;
}
枚举每个点,判断是否y,n都存在解,如果都存在即为?, 最后做一遍2SAT即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 105;
struct TwoSAT {
int n, S[maxn * 2], C;
bool mark[maxn * 2], must[maxn * 2];
vector<int> G[maxn * 2];
void init (int n) {
this->n = n;
memset(must, 0, sizeof(must));
for (int i = 0; i < n*2; i++) G[i].clear();
}
void clear() { memcpy(mark, must, sizeof(must)); }
void addClause(int x, int xflag, int y, int yflag) {
x = x * 2 + xflag;
y = y * 2 + yflag;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
void draw(int u) {
must[u] = true;
for (int i = 0; i < G[u].size(); i++)
if (!must[G[u][i]]) draw(G[u][i]);
}
bool dfs (int u) {
if (mark[u^1]) return false;
if (mark[u]) return true;
mark[u] = true;
S[C++] = u;
for (int i = 0; i < G[u].size(); i++)
if (!dfs(G[u][i])) return false;
return true;
}
bool solve () {
for (int i = 0; i < 2*n; i += 2) {
if (mark[i] && mark[i+1]) return false;
if (!mark[i] && !mark[i+1]) {
C = 0;
if (!dfs(i)) {
while (C) mark[S[--C]] = false;
if (!dfs(i+1)) return false;
}
}
}
return true;
}
}solver;
int N, M, T[maxn];
void init () {
int k, x[10], y[10];
char s[10];
solver.init(N);
memset(T, 0, sizeof(T));
while (M--) {
scanf("%d", &k);
for (int i = 0; i < k; i++) {
scanf("%d%s", &x[i], s);
x[i]--; y[i] = s[0] == 'y' ? 0 : 1;
}
if (k >= 3) {
for (int i = 0; i < k; i++)
for (int j = i + 1; j < k; j++)
solver.addClause(x[i], y[i], x[j], y[j]);
} else {
for (int i = 0; i < k; i++)
solver.must[x[i]*2+y[i]] = true;
}
}
}
int main () {
int cas = 1;
while (scanf("%d%d", &N, &M) == 2 && N + M) {
init();
for (int i = 0; i < 2*N; i++)
if (solver.must[i]) solver.draw(i);
for (int i = 0; i < 2*N; i += 2) {
if (solver.must[i] || solver.must[i+1]) continue;
solver.clear();
solver.mark[i] = true;
bool flag1 = solver.solve();
solver.clear();
solver.mark[i+1] = true;
bool flag2 = solver.solve();
if (flag1 && flag2) T[i/2] = 1;
}
solver.clear();
printf("Case %d: ", cas++);
if (!solver.solve()) printf("impossible\n");
else {
for (int i = 0; i < N; i++) {
if (T[i]) printf("?");
else if (solver.mark[i*2]) printf("y");
else printf("n");
}
printf("\n");
}
}
return 0;
}
相关文章推荐
- ajax学习第一课
- MySQLSlap简介和测试
- 日历小案列
- Error:Cannot build Artifact 'art_training:war exploded' because it is included into a circular depen
- 黑马程序员——C语言之指针数组和数组指针的区别
- angularJS的controller之间如何正确的通信
- solr.net的使用
- HDU 4540 威威猫系列故事——打地鼠(树塔问题简单变形)
- iCheat 使用教程
- hdoj 2122Ice_cream’s world III 【最小生成树 kruskal && prim】
- Android 监听apk安装替换卸载广播的实现代码
- JS常用正则表达式
- C++的构造函数和析构函数
- ANGULAR JS PROMISE使用
- uva 10510 - Cactus(仙人掌图)
- 京东众筹双色球中奖号计算方法
- 【oracle案例】ORA-01102: cannot mount database in EXCLUSIVE mode
- Queue(队列) Stack(堆栈)
- 零基础学python-15.3 函数的定义、调用与多态
- Missing number - 寻找缺失的那个数字