UVA1086 The Ministers' Major Mess

題目鏈接:

UVA
洛谷

題目大意:

有n個人對m個方案投票,每個人最多隻能對其中的4個方案投票(少投的票相當於棄權),每一票要麼支持要麼反對。問是否存在一個最終決定,使得每個投票人都有超過一半的投票被採納,在所有可能的最終決定中,哪些方案的狀態是確定的。

題解:

每個方案只有實施和不實施兩種狀態,想到2-sat。
每個人的投票相當於約束條件。因爲每個人都要有超過一半的投票被採納,如果他只投了投了2票及以下,那麼他的投票就應該全部被採納;如果他投了3票或者4票,他最多隻有一票沒有被採納,也就是說他投的票中兩兩之間必有一票被採納。
判斷哪些方案是確定的,可以依次對每個方案分別取真與假再跑一邊2-sat判斷能否成立。
關於 2-SAT(tarjan求法)

代碼:

#include <bits/stdc++.h>
#define LL long long
#define LD long double
#define ULL unsigned long long
#define UI unsigned int
#define PII pair<int,int>
#define MPII(x,y) pair<int,int>{x,y}
#define _for(i,j,k) for(int i=j;i<=k;i++)
#define for_(i,j,k) for(int i=j;i>=k;i--)
#define efor(i,u) for(int i=head[u];i;i=net[i])
#define lowbit(x) (x&-x)
#define ls(x) x<<1
#define rs(x) x<<1|1
#define inf 0x3fffffff
//#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
const int maxn = 2e4 + 5;
const int M = 1e9 + 7;
inline int mad(int a,int b){return (a+=b)>=M?a-M:a;}
//2-SAT板子
struct TwoSAT{ //2*i+1爲真,2*i爲假
	int n;
	vector<int> G[maxn*2];
	bool mark[maxn*2];
	int S[maxn*2],c;
	bool dfs(int x){
		if(mark[x^1]) return false;
		if(mark[x]) return true;
		mark[x]=true;
		S[c++]=x;
		for(int i=0;i<(int)G[x].size();i++)
			if(!dfs(G[x][i])) return false;
		return true;
	}
	void dfs_fix(int x){
		mark[x]=true;
		for(auto y:G[x]){
			if(!mark[y]) dfs_fix(y);
		}
	}
	void init(int n){
		this->n=n;
		for(int i=0;i<n*2;i++) G[i].clear();
		memset(mark,0,sizeof(mark));
	}
	void clear(){
		memset(mark,0,sizeof(mark));
	}
	void add_clause(int x,int xval,int y,int yval){ //條件 x爲xval或者y爲yval 
		x = (x<<1)|xval;
		y = (y<<1)|yval;
		G[x^1].push_back(y);
		G[y^1].push_back(x);
	}
	void add_fixed(int x,int val){ //x恆爲val 
		x = (x<<1)|val;
		dfs_fix(x);
	}
	bool solve(){
		for(int i=0;i<n*2;i+=2){
			if(mark[i] && mark[i+1]) return false;
			if(!mark[i]&&!mark[i+1]){
				c=0;
				if(!dfs(i)){
					while(c>0) mark[S[--c]]=false;
					if(!dfs(i+1)) return false;
				}
			}
		}
		return true;
	}
};
TwoSAT sat;
int p[5],c[5],mustbe[maxn];
string an;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,m,k,kase=0;char ch;
	while(cin>>n>>m,n|m){
		an.clear();
		sat.init(2*n);
		_for(i,0,n) mustbe[i]=-1; 
		_for(i,1,m){
			cin>>k;
			_for(j,1,k){
				cin>>p[j]>>ch;
				c[j]= ch=='n'?0:1;
			}
			if(k>=3)
			_for(j,1,k){
				_for(d,j+1,k){
					sat.add_clause(p[j]-1,c[j],p[d]-1,c[d]);
				}
			}
			else{
				_for(j,1,k){
					sat.add_fixed(p[j]-1,c[j]);
					mustbe[p[j]-1]=c[j];
				}
			}
		}
		cout<<"Case "<<++kase<<": ";
		if(sat.solve()){
			for(i,0,n-1){
				if(mustbe[i]==-1){
					sat.clear();
					_for(j,0,n-1){
						if(mustbe[j]!=-1) sat.add_fixed(j,mustbe[j]);
					}
					sat.add_fixed(i,0);
					if(!sat.solve()){
						an+='y';continue;
					}
					sat.clear();
					_for(j,0,n-1){
						if(mustbe[j]!=-1) sat.add_fixed(j,mustbe[j]);
					}
					sat.add_fixed(i,1);
					if(!sat.solve()){
						an+='n';continue;
					}
					an+='?';
				}
				else{
					an += (mustbe[i]?'y':'n');
				}
			}
			cout<<an<<"\n";
		}
		else{
			cout<<"impossible\n";
		}
	}
	return 0;
}
```cpp
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章