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. Codeforces Round #321 (Div. 2) D. Kefa and Dishes 状压dp

    题目链接: 题目 D. Kefa and Dishes time limit per test:2 seconds memory limit per test:256 megabytes 问题描述 W ...

  2. oracle 条件:1=1或1=0,动态添加条件

    看到where语句中有条件:where 1=1    和    1=2或1<>1 用途:     1=1:是为了添加条件时使用and并列其他条件时使用的(动态连接后续条件)     比如: ...

  3. [转载]MongoDB 标准连接字符串

    MongoDB 标准连接字符串 mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[data ...

  4. memcached+php客户端

    连接memcached <?php $mem = new Memcache; $mem->connect('localhost',11211) or die("connected ...

  5. UDP TCP 消息边界

    先明确一个问题,如果定义了一个数据结构,大小是,比方说 32 个字节,然后 UDP 客户端连续向服务端发了两个包.现在假设这两个包都已经到达了服务器,那么服务端调用 recvfrom 来接收数据,并且 ...

  6. 【WCF--初入江湖】08 并发与实例模式

    08 并发与实例模式 1. 实例上下文模式   一个服务代理:servicePoxy ChannelFactory<IService1> factoryservicel = new Cha ...

  7. 01-04-02【Nhibernate (版本3.3.1.4000) 出入江湖】HQL查询

    public IList<Customer> GetAllHql() { IList<Customer> result = null; ISession session = _ ...

  8. UVALive 3977

    直接搜索,简单题: #include<cstdio> #include<cstring> #include<cmath> #include<algorithm ...

  9. Browser detect

    A useful but often overrated JavaScript function is the browser detect. Sometimes you want to give s ...

  10. substr_replace()函数:将手机号中间4位隐藏为*号

    <?php $mobile = "15810320826"; echo substr_replace($mobile,'****',3 , 4); ?> substr_ ...