题目链接:https://cn.vjudge.net/contest/209474#problem/C

题目大意:

一共有m个提案,n个政客,每个政客都会对一些提案(最多四个)提出自己的意见——通过或者不通过。一个政客获得满意结果,当且仅当他的意见被满足了超过(注意是超过,即大于)一半,请问有没有这样的方案,使n个政客都满意?如果存在,输出所有方案。(这个所有的意思是一个提案如果只能是“通过”决策(在所有方案里都是通过),输出’y‘,只能不通过输出’n’,可以通过也可以不通过(有的方案是y,有的是n)输出‘?’)

解题思路:

本来想写在《浅谈2-SAT》里,想了想由于这道题比较巧妙,还是单独提出来写。巧妙之处在于1、寻找所有可行方案。2、问题到标准模型的转化。

先谈一下第二点。

一个政客满意,当且仅当他有一半以上的观点被采纳。也就是说,对于只提出一个提案和两个提案的人,只有他提出的所有观点都被采纳,这个人才会满意。对于提出三个提案的人,至少要满足两个观点(最多有一个不满足);对于提出四个提案的人,至少要满足三个观点(最多有1个不满足)。

每个提案有通过和不通过两种互斥状态,对于观点数量小于等于2的人,他所提出的提案有固定状态(不对称图),对于观点数大于等于3的人,我们如果令其中一个观点为不满足,那么其他的观点都必须满足。

由此我们建立了一个部分确定值的2-SAT图像。

再谈第一点。

这道题的难点其实我自我感觉在第一点。令人惊讶的是,第一点并没有什么高端的处理方法,仅仅是暴力枚举,如果一个提案两种状态的2-SAT图像都成立,那么就是?,只成立一种就是对应结果。如果两种都不成立那么就无解。

下面放有详细注释的9msAC代码并附了几组数据debug(欢迎hack):

 /* by Lstg */
/* 2018-03-07 00:33:58 */ #include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
#define MAXN 5100
using namespace std; vector<int>g[MAXN]; bool mark[MAXN],f[MAXN];
int stk[MAXN],top,n,lq[MAXN];
char ans[]; int _max(int a,int b){return a>b?a:b;}
int _abs(int x){return x<?-x:x;} void _clean(){ for(int i=;i<=*n+;i++){
g[i].clear();
mark[i]=;
f[i]=false;
}
} bool _dfs(int x){ if(mark[x^])return false;
if(mark[x])return true;
mark[x]=true;
stk[++top]=x;
for(int i=;i<g[x].size();i++)
if(!_dfs(g[x][i]))return false;
return true;
} bool _Twosat(){ for(int i=;i<=*n+;i+=)
if(!mark[i]&& !mark[i+]){
top=;
if(!_dfs(i)){
while(top)
mark[stk[top--]]=false;
if(!_dfs(i+))return false;
}
}
return true;
} void _addside(int k){ for(int i=;i<=k;i++)
for(int j=;j<=k;j++)
if(j!=i)
g[lq[i]^].push_back(lq[j]);//lq[i]^1表示状态的反面,即不满足。在此情况下其他的状态必须满足 } bool _check(){ int i;
for(i=;i<=*n+;i++)
if(f[i]&&!_dfs(i))return false;//如果不能满足固定的状态值就无解
memcpy(f,mark,sizeof(mark));//f数组已经没用了,用来当过渡
//printf("n=%d\n",n);
if(!_Twosat())return false;//如果满足了所有固定状态却不能满足整个2-SAT图,无解
//puts("haha!\n");
for(i=;i<=n;i++){
memcpy(mark,f,sizeof(f));//固定状态都满足的残余2-SAT图作为起始图像
top=;
if(!(_dfs(*i)&&_Twosat()))ans[i]='n';/*这里可能有点难理解,我写的确实很绕,没必要跟我一样,
这里的意思是如果不满足该提案通过,那么这个提案就一定是不通过(因为无解的情况已经全排除了,一定有解,这个提案通过却不满足图像,那么这个提案一定通不过)*/
else{//如果提案可以通过
memcpy(mark,f,sizeof(f));
top=;
if(_dfs(*i+)&&_Twosat())ans[i]='?';//验证是否也可以不通过
else ans[i]='y';
} }
return true;//返回有解
} int main(){ //freopen("C.txt","w",stdout);
int m,k,i,j,a,x;
char ch[];
int T=;
while(true){ scanf("%d%d",&n,&m);
if(m+n==)return ;
_clean(); for(i=;i<=m;i++){
scanf("%d",&k); for(j=;j<=k;j++){
scanf("%d%s",&x,ch); a=(ch[]=='y'?:);//2*ii表示通过,2*ii+1表示不通过 if(k<=)f[x*+a]=true;//f数组表示有确定状态的提案
else lq[j]=x*+a;//lq数组为一会儿构图的媒介
}
if(k>=)_addside(k);//用lq数组构图
}
printf("Case %d: ",++T);
if(!_check())printf("impossible\n");
else{
for(i=;i<=n;i++)
putchar(ans[i]);
putchar();
}
}
return ;
}
/*
1 1
1 1 n
1 1
1 1 y 3 2
3 1 y 2 y 3 n
3 1 n 2 n 3 y 3 2
3 1 y 2 n 3 n
3 1 n 2 n 3 n 3 2
3 1 y 2 y 3 n
3 1 y 2 n 3 n 4 2
4 1 y 2 y 3 n 4 n
3 2 n 3 n 4 n
3 2
3 1 y 2 y 3 n
3 1 y 2 n 3 n */

【2-SAT】The Ministers’ Major Mess UVALive – 4452的更多相关文章

  1. UVALive 4452 The Ministers' Major Mess(2-sat)

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

  2. uvalive 4452 The Ministers’ Major Mess

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

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

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

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

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

  5. uva1086 The Ministers' Major Mess

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

  6. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  7. Python学习【第一篇】Python简介

    Python简介 Python前世今生 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言. 现在,全世界差不多有600多种编 ...

  8. Python【第一篇】基础介绍

    一.本节主要内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc文件 数据类型初识 数据运算 表达式if ...else语 ...

  9. 【WebApi系列】浅谈HTTP

    [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi如何传递参数 [04]详解WebApi测试和PostMan [05]浅谈WebApi Core ...

随机推荐

  1. 图论&搜索:K短路-启发式搜索

    判断第k短路的权值是否小于T 直接把队友的代码拿过来了,一定很经典 #include <iostream> #include <queue> #include <cstr ...

  2. 关于Java泛型深入理解小总结

    1.何为泛型 首先泛型的本质便是类型参数化,通俗的说就是用一个变量来表示类型,这个类型可以是String,Integer等等不确定,表明可接受的类型,原理类似如下代码 int pattern; //声 ...

  3. 51nod 1140 矩阵相乘结果的判断

    给出三个N*N的矩阵A, B, C,问A * B是否等于C?   Input 第1行,1个数N.(0 <= N <= 500) 第2 - N + 1行:每行N个数,对应矩阵A的元素.(0  ...

  4. 【BZOJ】1537: [POI2005]Aut- The Bus

    [算法]DP+线段树求区间max(二维偏序) [题解] 状态转移方程:f[i]=max(f[j]+v[i]),x[j]<x[i]&&y[j]<y[i]. 观察j的条件限制显 ...

  5. matlab前景分割

    用最简单的差分法实现了一下前景分割.使用的mall数据集. 思路是这样的:首先设定一个队列的长度,若读取的图片张数少于队列长度则以当前读取到的图片做平均.否则则以队列中的图片做平均. 这样之后和当前图 ...

  6. 郑轻校赛 2127 tmk射气球 (数学)

    Description 有一天TMK在做一个飞艇环游世界,突然他发现有一个气球匀速沿直线飘过,tmk想起了他飞艇上有一把弓,他打算拿弓去射气球,为了提高射击的准确性,他首先在飞艇上找到一个离气球最近的 ...

  7. Msql中的触发器

    解发器 当执行某种操作时解发的行为. 比如, 当表变动时触发的动作. 像商城订单, 当下单时, 库存减少. 语法: create trigger trigger_name after/befor in ...

  8. BurpSuite 设置Hostname Resolution

    #写在前面 这种情况你可能遇到过: 对方用了CDN, 你查到了对方真实IP, 但还不能100%肯定. 这时候, 最好的测试就是 win/linux修改HOST文件 Win重启电脑 Linux重启网络 ...

  9. windows安装linux虚拟机、修改apt源

    记录一下windows安装虚拟机以及初始配置的一些坑. 安装VMware Workstation 直接百度搜索VMware,选择合适的版本下载: 按照一般软件的安装步骤安装VMware Worksta ...

  10. android 系统的休眠与唤醒+linux 系统休眠

    Android休眠与唤醒驱动流程分析 标准Linux休眠过程: powermanagement notifiers are executed with PM_SUSPEND_PREPARE tasks ...