题意:

有一些部长需要对某些账单进行投票。

一个部长最多对4个账单进行投票,且每票对一个账单通过,要么否决。

问是否存在一个方案使得所有部长有超过半数的投票被通过,如果有,那么说明哪些账单的决定是明确的,哪些是不明确的;否则说明不可能。

思路:

2-SAT。

一开始觉得这是一个k-SAT问题,但是因为有着所有部长的投票有超过半数被通过这个条件存在,所以可以简化。

对于一票或者两票的部长,那么所有条件都要被满足,意味着某些账单的决定是确定。

如何表示一个条件是确定的呢,这是从这个题中学习到的一点,不是简单的标记这个条件的真假,而是从自己向自己的对立面连边,如果在搜索的过程中,发现自己和自己的对立面均被标记,那么就产生矛盾从而不满足条件了。

然后是对于3票或者4票的部长,要超过一半,如果一旦一个账单取相反的决定,那么其它账单都要取与输入相同的决定才能保证查过一半,再根据这个条件连边。

之后再解决如何确定一个账单的决定是否明确,对于一个账单,如果标记为通过能找到方案,否决也能找到方案,那么这个账单的决定就是不明确的,否则就可以判断其是明确的。在每一次标记了一个条件进行搜索之后,都必须将这个过程中标记过的点全部初始化,才能保证下一次搜索的正确。

代码:

 #include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; const int maxn = ; struct twosat
{
int n;
vector<int> g[maxn*];
bool mark[maxn*];
int s[maxn*],c;
int ty[maxn]; bool dfs(int x)
{
if (mark[x^]) return false;
if (mark[x]) return true; mark[x] = true; s[c++] = x; for (int i = ;i < g[x].size();i++)
{
if (!dfs(g[x][i])) return false;
} return true;
} void add_clause(int x,int xval,int y,int yval)
{
x = x * + xval;
y = y * + yval; g[x^].push_back(y);
} void init(int n)
{
this -> n = n;
memset(mark,,sizeof(mark));
memset(ty,,sizeof(ty));
for (int i = ;i <= n * ;i++) g[i].clear();
} bool solve()
{
for (int i = ;i < n * ;i += )
{
if (!mark[i] && !mark[i+])
{
c = ; if (!dfs(i))
{
while (c > ) mark[s[--c]] = ;
if (!dfs(i+)) return false;
else
{
while (c > ) mark[s[--c]] = ;
ty[i/] = ;
}
}
else
{
while (c > ) mark[s[--c]] = ;
if (!dfs(i+))
{
ty[i/] = ;
while (c > ) mark[s[--c]] = ;
}
else
{
ty[i/] = ;
while (c > ) mark[s[--c]] = ;
}
}
}
else
{
if (mark[i]) ty[i/] = ;
else ty[i/] = ;
}
} return true;
} /*void judge()
{
for (int i = 0;i < n * 2;i += 2)
{
if (!mark[i] && !mark[i+1])
{
c = 0; bool tr = 0;
bool fa = 0; if (dfs(i))
{
fa = 1;
while (c > 0) mark[s[--c]] = 0;
} if (dfs(i+1))
{
tr = 1;
while (c > 0) mark[s[--c]] = 0;
} if (tr && fa) ty[i/2] = 3;
else if (tr) ty[i/2] = 2;
else ty[i/2] = 1;
}
else
{
//if (i == 0) printf("2333");
if (mark[i]) ty[i/2] = 1;
else ty[i/2] = 2;
}
}
}*/
}twosat; int main()
{
int n,m;
int kase = ; while (scanf("%d%d",&n,&m) != EOF)
{
if (n == && m == ) break; twosat.init(n); for (int i = ;i < m;i++)
{
int k;
scanf("%d",&k); int a[];
char ch[][]; for (int j = ;j < k;j++)
{
scanf("%d%s",&a[j],ch[j]);
a[j]--;
} //for (int j = 0;j < k;j++) vis[a[j]] = 1; if (k <= )
{
for (int j = ;j < k;j++)
{
if (ch[j][] == 'y') twosat.add_clause(a[j],,a[j],);
else twosat.add_clause(a[j],,a[j],);
}
}
else
{
bool b[]; for (int j = ;j < k;j++)
{
b[j] = ch[j][] == 'y' ? : ;
} for (int j = ;j < k;j++)
{
for (int l = ;l < k;l++)
{
if (j != l)
{
twosat.add_clause(a[j],b[j],a[l],b[l]);
}
}
}
}
} if (twosat.solve())
{
//twosat.judge(); printf("Case %d: ",++kase); for (int i = ;i < n;i++)
{
switch(twosat.ty[i])
{
case : printf("n");break;
case : printf("y");break;
case : printf("?");break;
}
}
printf("\n");
}
else printf("Case %d: impossible\n",++kase);
} return ;
}

uvalive 4452 The Ministers’ Major Mess的更多相关文章

  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 (TwoSat)

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

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

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

  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. 记一次jdk升级引起的 Unsupported major.minor version 51.0

    之前jdk 一直是1.6,tomcat 是6.x 版本,, 现在引入的新的jar, 出现 Caused by: java.lang.UnsupportedClassVersionError: org/ ...

  7. 解决Unsupported major.minor version 51.0错误

    解决Unsupported major.minor version 51.0错误使用jdk6运行项目时发生了Unsupported major.minor version 51.0错误.经过网上搜索发 ...

  8. Unsupported major.minor version 51.0

    org/jboss/as/domain/management/security/adduser/AddUser : Unsupported major.minor version 51. 0 已编译好 ...

  9. Unsupported major.minor version 52.0问题的解决

    下载Tomcat9.0,解压后安装运行,结果启动失败,进入logs文件夹看里面的日志文件,提示是Unsupported major.minor version 52.0错误,这是因为Tomcat版本过 ...

随机推荐

  1. js如何判断哪个按钮被点击了?

    用事件委托,然后判断target,代码如下: $(docuement).on('click',function(event){ event.target... }) 例如:点击.c1之外任意地方的时候 ...

  2. 20165225 《Java程序设计》第二周学习总结

    20165225<Java程序设计>第二周学习总结 1.视频与课本中的学习: ##### 1.标识符: 字母.下划线.美元符号.数字(不能是true,false,null还有关键字). # ...

  3. Qt Multimedia 模块类如何使用?(表格)

    qt 多媒体模块介绍 类名 英文描述 中文描述 QAudioBuffer Represents a collection of audio samples with a specific format ...

  4. POJ2274 Long Long Message 字符串

    正解:SA/哈希+二分 解题报告: 传送门! 啊先放下翻译,,,?大意就有两个字符串,求这两个字符串的最长公共子串 先港SA的做法趴 就把两个子串拼接起来,然后题目就变成了求后缀的最长公共前缀了 所以 ...

  5. GBDT原理学习

    首先推荐 刘建平 的博客学习算法原理推导,这位老师的讲解都很详细,不过GBDT的原理讲解我没看明白, 而是1.先看的https://blog.csdn.net/zpalyq110/article/de ...

  6. 在asp.net中使用瀑布流,无限加载

    页面中代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1 ...

  7. 数字转换大写人民币的delphi实现

    function TForm1.changeRmb(const strRmb:string):string; var txt,strhighlevel:string; i,n,m,ilen,ipos: ...

  8. 微信小程序github源码

    https://github.com/justjavac/awesome-wechat-weapp https://www.cnblogs.com/tuyile006/p/6268961.html h ...

  9. 【LeetCode每天一题】3Sum Closest(最接近的三数和)

    Given an array nums of n integers and an integer target, find three integers in nums such that the s ...

  10. jenkins 设置钉钉通知--钉钉机器人

    https://blog.csdn.net/workdsz/article/details/77531802