• 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;
    }
  • 相关阅读:
    redolog switch会发生完全检查点还是增量检查点?
    4G牌照发放生变 专家谏言电信联通如何选择
    [财富]iPhone如何征服日本?
    审计中移动现多处问题或致地方高层落马
    诺基亚CEO:Lumia不会像安卓推廉价版机型
    菜鸟学JDBC(二)
    简易网页采集器的实现
    手Q与微信:最终结局将会是手足相残!
    做网站Http状态码详解
    PHP $_SERVER['HTTP_REFERER'] 获取前一页面的 URL 地址
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3050896.html
Copyright © 2020-2023  润新知