码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive - 4452 The Ministers' Major Mess(2-SAT)

时间:2015-08-09 17:13:31      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有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 1010

struct 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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

UVALive - 4452 The Ministers' Major Mess(2-SAT)

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/47377103

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!