UVA-1086 - 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; }