博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uva1086 The Ministers' Major Mess
阅读量:5014 次
发布时间:2019-06-12

本文共 3256 字,大约阅读时间需要 10 分钟。

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

数据范围:n≤1000,m≤5000,1≤ki≤4

 

首先这是一些布尔变量的真假的问题,这让我们联想到2-SAT

仔细观察题意发现,k=1,2的时候所投的1个/2个提议的结果必须和投的票相同,k=3和4的时候最多允许有一个提议的结果和投的票不同.

因为2-SAT问题是对两个变量的约束,我们发现,如果k=3,某个人要求A,B,C三个变量至少两个为真,那么这三个变量中任意两个至少一个为真,也就是”A或B”,”B或C”,”A或C”

K=4的时候,添加6条限制即可.

接下来枚举每个变量的取值,分别添加某个变量必须为真/假的条件,用线性做法做2n次2-SAT,然后这样是卡在1s左右.我们发现,只要找出一个可行方案,就能对n个变量都给出一个可行的取值,然后就把2-SAT次数减少到了n次,就可以过了

吐槽:考试的题是单组数据,UVA上多组数据,输出格式还不一样…加初始化,改输出格式的时候挂了5次(最有趣的一次是考试的时候没有输出文末回车因为是单组数据没出事,多组数据的时候就成了每组数据的输出之间没有回车…)

#include
#include
#include
using namespace std;const int maxn=2005,maxm=500005;struct edge{ int to,next;}lst[maxm],lst2[maxm];int len=1,first[maxn],len2=1,first2[maxn];void addedge(int a,int b){
//printf("%d %d\n",a,b); lst[len].to=b;lst[len].next=first[a];first[a]=len++;}void addedge2(int a,int b){
//printf("%d->%d\n",a,b); lst2[len2].to=b;lst2[len2].next=first2[a];first2[a]=len2++;}int conv[maxn][2];int ok[maxn][2];void AddTrue(int x){ addedge(conv[x][0],conv[x][1]);}void AddFalse(int x){ addedge(conv[x][1],conv[x][0]);}void AddOr(int x1,int t1,int x2,int t2){ addedge(conv[x1][t1^1],conv[x2][t2]);addedge(conv[x2][t2^1],conv[x1][t1]);}int n,m,k;int a[10],b[10];char buf[5];int s[maxn],top,dfn[maxn],low[maxn],belong[maxn],tot,T;bool ins[maxn];void dfs(int x){ s[top++]=x;ins[x]=true; dfn[x]=low[x]=++T; for(int pt=first[x];pt;pt=lst[pt].next){ if(!dfn[lst[pt].to]){ dfs(lst[pt].to); if(low[lst[pt].to]
scc[maxn]; int lim=2*n;cnt=0; for(int i=1;i<=lim;++i)sz[belong[i]]++,scc[belong[i]].push_back(i); for(int i=1;i<=lim;++i){ for(int pt=first[i];pt;pt=lst[pt].next){ if(belong[i]!=belong[lst[pt].to]){ addedge2(belong[i],belong[lst[pt].to]); } } } for(int i=1;i<=tot;++i){ if(!vis[i])toposort(i); } for(int i=1;i<=cnt;++i){ int x=toposeq[i];int flag=1;//printf("%d\n",x); if(choose[x]!=0)continue; for(int pt=first2[x];pt;pt=lst2[pt].next){ if(choose[lst2[pt].to]==-1){ flag=-1;break; } } choose[x]=flag; for(int j=0;j
=1;--i){ for(int k=0;k<2;++k){ if(ok[i][k]==1)continue; int tmp=first[conv[i][k^1]]; if(k==1)AddTrue(i); else AddFalse(i); if(Tarjan()){ ok[i][k]=1; } len--; first[conv[i][k^1]]=tmp; } }}int main(){ int t=0; while(scanf("%d%d",&n,&m),n!=0){ memset(first,0,sizeof(first));len=1;memset(first2,0,sizeof(first2));len2=1; memset(conv,0,sizeof(conv));memset(ok,0,sizeof(ok)); memset(choose,0,sizeof(choose));memset(vis,0,sizeof(vis)); memset(sz,0,sizeof(sz)); for(int i=1;i<=n;++i){ conv[i][0]=2*i-0;conv[i][1]=2*i-1; } for(int i=1;i<=m;++i){ scanf("%d",&k); for(int j=1;j<=k;++j){ scanf("%d",&a[j]); scanf("%s",buf); if(buf[0]=='y')b[j]=1; else b[j]=0; } if(k==1){ if(b[1]==1)AddTrue(a[1]); else AddFalse(a[1]); }else if(k==2){ for(int j=1;j<=2;++j){ if(b[j]==1)AddTrue(a[j]); else AddFalse(a[j]); } }else{ for(int j=1;j<=k;++j){ for(int l=j+1;l<=k;++l){ AddOr(a[j],b[j],a[l],b[l]); } } } } printf("Case %d: ",++t); if(Tarjan()){ get_solution(); work(); for(int i=1;i<=n;++i){ if(ok[i][0]==1&&ok[i][1]==1)printf("?"); else printf("%c",(ok[i][0]==1)?'n':'y'); }printf("\n"); }else{ puts("impossible"); } } return 0;}

 

转载于:https://www.cnblogs.com/liu-runda/p/6401689.html

你可能感兴趣的文章
C# 其他的Url 文件的路径转化为二进制流
查看>>
cmake使用
查看>>
ios7上隐藏status bar
查看>>
构造方法和全局变量的关系
查看>>
python3基础05(有关日期的使用1)
查看>>
ArrayList的使用方法
查看>>
面向对象高级
查看>>
Bitwise And Queries
查看>>
打印Ibatis最终的SQL语句
查看>>
HBase之八--(3):Hbase 布隆过滤器BloomFilter介绍
查看>>
oracle连接问题ORA-00604,ORA-12705
查看>>
NOI 2019 退役记
查看>>
java的几个日志框架log4j、logback、common-logging
查看>>
Java从零开始学十三(封装)
查看>>
Python2和Python3中的rang()不同之点
查看>>
MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作)...
查看>>
UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。
查看>>
记忆--1.致我们不可缺少的记忆
查看>>
lintcode28- Search a 2D Matrix- easy
查看>>
react项目
查看>>