UVA1086 The Ministers' Major Mess(TwoSat)

题意:有N个方案M个投票人,每个投票人最多能投4个方案,问满足每个投票人超过一半的建议被采用的方案.若不存在输出"impossible"

分析:对于投票人,若提出的方案少于3个,则需要全部满足才能满足题意,若大于等于三个则最多只能有一个方案不被满足

答案输出对于每个方案采纳和不采纳都Twosat一遍,若都满足输出"?",若都不满足则没有方案满足题意,输出"impossible",若只能采纳输出"y",不能采纳输出"n";

// File Name: 1086.cpp
// Author: Zlbing
// Created Time: 2013/4/29 16:00:27

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=250;
struct TwoSAT{
    int n;
    vector<int>G[MAXN*2];
    bool mark[MAXN*2];
    stack<int>S;
    bool dfs(int x)
    {
        if(mark[x^1])return false;
        if(mark[x])return true;
        mark[x]=true;
        S.push(x);
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i];
            if(!dfs(v))return false;
        }
        return true;
    }
    void init(int _n)
    {
        n=_n;
        for(int i=0;i<2*n;i++)
            G[i].clear();
        memset(mark,0,sizeof(mark));
    }
    void add_clause(int x,int y)
    {
        G[x].push_back(y);
    }
    void mark_clear(){
        memset(mark,0,sizeof(mark));
    }
    bool solve()
    {
        for(int i=0;i<2*n;i=i+2)
        {
            if(!mark[i]&&!mark[i+1]){
                  while(!S.empty())
                  {
                      S.pop();
                  }
                if(!dfs(i))
                {
                    while(!S.empty())
                    {
                        mark[S.top()]=false;
                        S.pop();
                    }
                    if(!dfs(i+1))return false;
                }
            }
        }
        
//        for(int i=0;i<2*n;i++)
//            if(mark[i])printf("%d ",T[i/2][i%2]);
//        printf("\n");
        return true;
    }
};

int n,m;
TwoSAT solver;
int A[MAXN];
void go()
{
    REP(i,0,n-1)
    {
        int cnt=0;
        solver.mark_clear();
        solver.add_clause(i*2+1,i*2);
        if(solver.solve())
            cnt+=1;
        solver.G[i*2+1].pop_back();
        solver.mark_clear();
        solver.add_clause(i*2,i*2+1);
        if(solver.solve())
            cnt+=2;
        solver.G[i*2].pop_back();
        if(cnt==0)
        {
            printf("impossible\n");
            return;
        }
        else if(cnt==1)
        {
            printf("y");
        }
        else if(cnt==2)
        {
            printf("n");
        }
        else {
            printf("?");
        }
    }
    printf("\n");
}
int main()
{
    int cas=0;
    while(~scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0)break;
        solver.init(n);
        int k;
        REP(j,1,m){
            scanf("%d",&k);
            REP(i,1,k)
            {
                int a;
                char ch[2];
                scanf("%d%s",&a,ch);
                a--;
                if(ch[0]=='y')A[i]=a*2;
                else A[i]=a*2+1;
            }
            if(k<3){
                REP(i,1,k)
                {
                    solver.add_clause(A[i]^1,A[i]);
                }
            }
            else{
                REP(i,1,k)
                    REP(t,1,k)
                    {
                        if(i==t)continue;
                        solver.add_clause(A[i]^1,A[t]);
                    }
            }
        }
        printf("Case %d: ",++cas);
        go();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/3050896.html