UVALive - 4452 The Ministers' Major Mess(2-SAT)
来源:互联网 发布:知乎匿名提问 编辑:程序博客网 时间:2024/05/17 02:08
题目大意:有n个人对m个方案投票,每个人最多只能对其中的4个方案投票(其他的相当于弃权),每一票要么支持要么反对。问是否存在一个最终决定,使得每个投票人都有超过一半的建议被采纳,在所有可能的最终决定中,哪些方案的态度是确定的
解题思路:参考了一下别人的思路,学习了
当想要确定某一个状态(i)时,可以用他的相反状态(i^1)和该状态建立一条边,那样的话,每当dfs到他的相反状态时,就会return false
在理解了上面的基础上,就可以建边了
首先,要有超过一半的投票被采纳。也就是说,当投票数小于等于2的时候,每一票都要被采纳,当投票数大于2时,只能有一票被否定,依此建边
接着就是判断能否被采纳了,可以枚举每个方案的最终决定,如果有一个方案无论是被否定还是被肯定都是错的话,那么就不可能满足所有人的要求了(超过一半的建议被采纳),可以在枚举的时候边记录最终状态的态度
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define N 110#define M 1010struct vote{ int bill, vote;}V[M][5];vector<int> G[M];int ans[N];int n, m;bool mark[N * 2];void AddEdge(int x, int valx, int y, int valy) { x = x * 2 + valx; y = y * 2 + valy; G[x].push_back(y);}void init() { for (int i = 0; i < 2 * n; i++) G[i].clear(); int t; char c; for (int i = 0; i < m; i++) { scanf("%d", &t); for (int j = 0; j < t; j++) { scanf("%d %c", &V[i][j].bill, &c); V[i][j].bill--; if (c == 'y') V[i][j].vote = 1; else V[i][j].vote = 0; } if (t <= 2) { for (int j = 0; j < t; j++) AddEdge(V[i][j].bill, V[i][j].vote ^ 1, V[i][j].bill, V[i][j].vote); } else { for (int j = 0; j < t; j++) for (int k = 0; k < t; k++) { if (j == k) continue; AddEdge(V[i][j].bill, V[i][j].vote ^ 1, V[i][k].bill, V[i][k].vote); } } }}int S[M];int c;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 TwoAST() { for (int i = 0; i < 2 * n; i += 2) { 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;}int cas = 1;void solve() { int i; for (i = 0; i < n; i++) { int tmp = 0; memset(mark, 0, sizeof(mark)); //第i个方案被否定时 AddEdge(i, 1, i, 0); if (TwoAST()) tmp += 1; G[(i << 1) ^ 1].pop_back(); //第i个方案被肯定时 memset(mark, 0, sizeof(mark)); AddEdge(i, 0, i, 1); if (TwoAST()) tmp += 2; G[(i << 1)].pop_back(); if (tmp == 0) break; else if(tmp == 1) ans[i] = 0; else if (tmp == 2) ans[i] = 1; else if (tmp == 3) ans[i] = 2; } printf("Case %d: ", cas++); if (i != n) { printf("impossible\n"); return ; } for (int i = 0; i < n; i++) { if (!ans[i]) printf("n"); else if(ans[i] == 1) printf("y"); else if(ans[i] == 2) printf("?"); } printf("\n");}int main() { while (scanf("%d%d", &n, &m) != EOF && n + m) { init(); solve(); } return 0;}
0 0
- UVALive - 4452 The Ministers' Major Mess(2-SAT)
- LA 4452 The Ministers' Major Mess(2-SAT)
- The Ministers' Major Mess UVALive
- UVA 1086 - The Ministers' Major Mess(2-sat)
- uva 1086 - The Ministers' Major Mess(2 SAT)
- LA 3514 The Ministers' Major Mess(2-SAT)
- uva 1086 - The Ministers' Major Mess(TwoSat)
- UVALIVE 4452(2-SAT变形)
- uvalive 3713 2-sat
- UVALive 3211 2-SAT问题
- UVALive 5010 2-sat+二分
- UVALive 3713 - Astronauts(2-SAT)
- UVALive - 3713 Astronauts(2-SAT)
- The Logging Mess
- The Java Logging Mess
- UVALive 3713 Astronauts(2SAT)
- UVALive - 3211 Now or later (2-SAT)
- UVALIVE 3713 Astronauts(2-SAT)
- 自定义注解
- Product of Array Except Self
- Android文件上传
- GDB调试程序(一)
- 【QQ机器人开发】茉莉QQ机器人3.X系列插件开发文档
- UVALive - 4452 The Ministers' Major Mess(2-SAT)
- TextView的一些使用
- poj3207Ikki's Story IV - Panda's Trick tarjan缩点
- 零基础学python-1.3 通过idle启动python
- 剑指offer刷题之java实现的栈的压入、弹出序列
- [php] 常用header
- 剩余系,剩余定理,同余定理,费马小定理的证明
- UVa 10815 Andy's First Dictionary
- LeetCode #1 Two Sum