2-sat。又学到了一种使用的方法:当确定选择某中状态A时,从它的对立状态A^1引一条边add(A^1,A),从而使凡是dfs经过对立状态,必然return false;即保证若存在一种可能性,必然是经过该状态A的。

题意:m个人对n个方案投票,每人之多投4票,是否存在一种方案使每个人所投的一半以上的票被采纳。依次输出每个议题最终的结果。

1、注意是一半以上,我一开始理解成一半,结果无法根据必然性建边。<=2票则都被采纳,<=4票则至多有一票不被采纳。

2、输出时要注意,因为每个议题的结果都不一定相同,所以需要一一判断。需要分别进行solve(i),和solve(i+1)。这里一开始我直接是把solve()函数中的dfs(i)和dfs(i+1)分开,wa了,后来考虑发现,solve()一次,是对遍历整个方案寻找可行性;而dfs()只是对一个连通的量做了标记。

注意:分别检查同一个议题的两种状态,确定从状态A经过,add(A^1,A),结束要记得G[i].pop_back();

 #include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std; const int MAXN=; struct Vote{
int v,c;
}vote[MAXN][]; bool mark[MAXN<<];
int res[MAXN];
int s[MAXN<<],c;
vector<int >G[MAXN<<]; void init(int n)
{
for(int i=;i<(n<<);i++)
G[i].clear();
memset(mark,,sizeof(mark));
} void add(int x,int dx,int y,int dy)
{
x=(x<<)+dx;
y=(y<<)+dy;
G[x].push_back(y);
} bool dfs(int x)
{
if(mark[x^])
return false;
if(mark[x])
return true;
s[c++]=x;
mark[x]=true;
for(int i=;i<G[x].size();i++)
if(!dfs(G[x][i]))
return false;
return true;
} bool solve(int n)
{
for(int i=;i<(n<<);i+=)
{
if(!mark[i]&&!mark[i+]){
c=;
if(!dfs(i)){
while(c>)
mark[s[--c]]=false;
if(!dfs(i+))
return false;
}
}
}
return true;
} bool test(int n)
{
for(int i=;i<n;i++)
{
int ans=;
memset(mark,,sizeof(mark));
add(i,,i,);
while(c>)
mark[s[--c]]=false;
if(solve(n))
ans+=;
G[(i<<)+].pop_back(); memset(mark,,sizeof(mark));
add(i,,i,);
while(c>)
mark[s[--c]]=false;
if(solve(n))
ans+=;
G[i*].pop_back(); if(ans==)
return false;
else if(ans==)
res[i]=-;
else if(ans==)
res[i]=;
else if(ans==)
res[i]=;
}
return true;
} int main()
{
int n,m;
int cnt=,ans;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m)
return ; init(n); //!!
for(int i=;i<m;i++)
{
scanf("%d",&ans); for(int j=;j<ans;j++)
{
int x;
char ch[];
scanf("%d %s",&x,ch);
vote[i][j].v=--x;
if(ch[]=='y')
vote[i][j].c=;
else
vote[i][j].c=;
}
if(ans<=){
for(int j=;j<ans;j++)
add(vote[i][j].v,vote[i][j].c^,vote[i][j].v,vote[i][j].c);
}else
for(int j=;j<ans;j++)
for(int k=;k<ans;k++)
{
if(j==k)
continue;
add(vote[i][j].v,vote[i][j].c^,vote[i][k].v,vote[i][k].c);
}
} memset(res,,sizeof(res));
printf("Case %d: ",++cnt);
if(!test(n))
printf("impossible\n");
else {
for(int i=;i<n;i++)
{
if(res[i]==)
printf("?");
else if(res[i]==)
printf("y");
else if(res[i]==-)
printf("n");
}
printf("\n");
}
}
return ;
}
/*
5 3
2 1 y 2 n
3 1 y 3 n 4 y
4 1 n 3 n 4 n 5 y
*/

UVALive 4452 The Ministers' Major Mess(2-sat)的更多相关文章

  1. UVaLive 4452 The Ministers' Major Mess (TwoSat)

    题意:有 m 个人对 n 个方案投票,每个人最多只能对其中的4个方案投票(其他的相当于弃权),每一票要么支持要么反对.问是否存在一个最终决定,使得每个投票人都有超过一半的建议被采纳,在所有可能的最终决 ...

  2. uvalive 4452 The Ministers’ Major Mess

    题意: 有一些部长需要对某些账单进行投票. 一个部长最多对4个账单进行投票,且每票对一个账单通过,要么否决. 问是否存在一个方案使得所有部长有超过半数的投票被通过,如果有,那么说明哪些账单的决定是明确 ...

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

    题目大意:有n个问题,m个人来投票,没人最多投4票,问该怎样决定才能使每个人都有超过一半的票数被认可? 题目分析:2-SAT问题.如果某个人投的票数少于2,则这两票军被采纳,如果票数至少三票,则最多有 ...

  4. 【2-SAT】The Ministers’ Major Mess UVALive – 4452

    题目链接:https://cn.vjudge.net/contest/209474#problem/C 题目大意: 一共有m个提案,n个政客,每个政客都会对一些提案(最多四个)提出自己的意见——通过或 ...

  5. UVALive 5966 Blade and Sword -- 搜索(中等题)

    题意:给一幅地图,P为起点,D为终点,'*'为传送阵,到达传送阵可以传到任意一个其他的传送阵,传到以后可以正常走或者再传回来,问P->D最短步数. 分析:这题一定要细心,分析要到位才能搞定,错一 ...

  6. uva1086 The Ministers' Major Mess

    题意:有n 个议案,m 个大臣,每个大臣会对其中的ki 个议案投票,为赞成或反对.现要你判断是否存在一种方案,使得每个大臣有大于一半的投票被满足.若存在,还需判断某个议案是不是一定要通过,或者一定不能 ...

  7. 【UVALive - 3211】Now or later (二分+2-SAT)

    题意: 有n架飞机需要着陆.每架飞机有两种选择,早着陆或者晚着陆,二选其一.现在为了保证飞机的着陆安全,要求两架着陆的飞机的时间间隔的最小值达到最大. 分析: 最小值最大问题我们想到二分答案.对于猜测 ...

  8. POJ 3678 Katu Puzzle(2 - SAT) - from lanshui_Yang

    Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a ...

  9. 学习笔记(two sat)

    关于two sat算法 两篇很好的论文由对称性解2-SAT问题(伍昱), 赵爽 2-sat解法浅析(pdf). 一些题目的题解 poj 3207 poj 3678 poj 3683 poj 3648 ...

随机推荐

  1. nginx + tomcat集群和动静资源分离

    开发的应用采用F5负载均衡交换机,F5将请求转发给5台hp unix服务器,每台服务器有多个webserver实例,对外提供web服务和socket等接口服务.之初,曾有个小小的疑问为何不采用开源的a ...

  2. javaScript基础之闭包

    不管是Jquery还是EXTJS,现代的js框架中大量应用了js的一些特性,比如:匿名函数,闭包等等,导致源代码非常难以阅读. 不过要想真正的使用好前台的UI技术,还是需要去深入的理解这些概念.   ...

  3. 阿里云CentOS6.3 安装MongoDB教程

    安装说明 系统环境:Centos-6.3安装软件:mongodb-linux-x86_64-2.2.2.tgz下载地址:http://www.mongodb.org/downloads安装机器:192 ...

  4. How to use Mac Terminal

    Mac OS X 启用超级用户的方法Root user,又名超级用户,是一个权力最高的Unix 账户,Root 的账户能在整个系统里任何部份进行任何“操作”,包括:拷贝档案.移动/移除档案.执行程序等 ...

  5. Embedding Lua in C: Using Lua from inside C.

    Requirments:     1: The Lua Sources.    2: A C compiler - cc/gcc/g++ for Unix, and Visual C++ for Wi ...

  6. Matlab程序 转C++/Opencv基于Mat 不可不知的17个函数

    1.matlab中的imread相当于OpenCV中的cvLoadImage(imageName,  CV_LOAD_IAMGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR): ...

  7. *[hackerrank]Jim Beam

    https://www.hackerrank.com/contests/infinitum-aug14/challenges/jim-beam 学习了线段相交的判断法.首先是叉乘,叉乘的几何意义是有向 ...

  8. python 常用数据结构使用

    python 字典操作 http://www.cnblogs.com/kaituorensheng/archive/2013/01/24/2875456.html python 字典排序 http:/ ...

  9. Delphi 发展历史

    自然人的软件著作权,保护期为自然人终生及其died后50年:软件是合作开发的,截止于最后died的自然人died后第50年的12月31日.法人或者其他组织的软件著作权,保护期为软件首次发表之后50年, ...

  10. Linux autoconf和automake使用

    作为Linux下的程序开发人员,一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的Mak ...