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
原创粉丝点击