您的位置:首页 > 其它

UVA 1086 - The Ministers' Major Mess(2-sat)

2014-09-01 18:22 197 查看


UVA 1086 - The Ministers' Major Mess

题目链接

题意:有n个方案,每个人投票,一个人最多投4张票,现在要有一个方案,使得满足所有人投票方案中有超过一半被满足,输出方案的对错,如果一个方案对错都可以,就输出?

思路:明显是二分图,一开始想错了,想从正着去把条件式化简,根本不可行

正确的做法是,反过来想,因为最多4张票并且超过1半,如果反过来想选哪些方案不满足,那么就只有1和0的情况,就很容易构造表达式了,然后就是2-sat,对于?的情况,只要遍历一遍,每个位置再加一条和原来条件相反的边然后做一次2-sat,如果还满足就是?,如果不满足就是位置的y或n

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXNODE = 105;

struct TwoSet {
int n;
vector<int> g[MAXNODE * 2];
bool mark[MAXNODE * 2];
int S[MAXNODE * 2], sn;

void init(int tot) {
n = tot * 2;
for (int i = 0; i < n; i += 2) {
g[i].clear();
g[i^1].clear();
}
memset(mark, false, sizeof(mark));
}

void add_Edge(int u, int uval, int v, int vval) {
u = u * 2 + uval;
v = v * 2 + vval;
g[u^1].push_back(v);
g[v^1].push_back(u);
}

void delete_Edge(int u, int uval, int v, int vval) {
u = u * 2 + uval;
v = v * 2 + vval;
g[u^1].pop_back();
g[v^1].pop_back();
}

bool dfs(int u) {
if (mark[u^1]) return false;
if (mark[u]) return true;
mark[u] = true;
S[sn++] = u;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (!dfs(v)) return false;
}
return true;
}

bool solve() {
for (int i = 0; i < n; i += 2) {
if (!mark[i] && !mark[i + 1]) {
sn = 0;
if (!dfs(i)){
for (int j = 0; j < sn; j++)
mark[S[j]] = false;
sn = 0;
if (!dfs(i + 1)) return false;
}
}
}
return true;
}
} gao;

const int N = 105;

int n, m;
int a[5];
bool b[5], save
;

int bitcount(int x) {
int ans = 0;
while (x) {
ans += (x&1);
x >>= 1;
}
return ans;
}

int main() {
int cas = 0;
while (~scanf("%d%d", &n, &m) && n || m) {
int k;
gao.init(n);

while (m--) {
scanf("%d", &k);
char c;
for (int i = 0; i < k; i++) {
scanf("%d %c", &a[i], &c);
a[i]--;
if (c == 'y') b[i] = true;
else b[i] = false;
}
if (k <= 2) {
for (int i = 0; i < k; i++)
gao.add_Edge(a[i], b[i], a[i], b[i]);
}
else {
for (int i = 0; i < k; i++) {
for (int j = i + 1; j < k; j++) {
gao.add_Edge(a[i], b[i], a[j], b[j]);
}
}
}
}
printf("Case %d: ", ++cas);
if (!gao.solve()) printf("impossible\n");
else {
for (int i = 0; i < n; i++)
save[i] = gao.mark[i * 2 + 1];
for (int i = 0; i < n; i++) {
memset(gao.mark, false, sizeof(gao.mark));
gao.add_Edge(i, !save[i], i, !save[i]);
if (gao.solve()) printf("?");
else printf("%c", save[i] ? 'y' : 'n');
gao.delete_Edge(i, !save[i], i, !save[i]);
}
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: