赛前告诉小朋友们去年区域赛出了两题2-sat,今年不会出了,然后我就错了。而且集训队的2-sat是我讲的,结果导致他们三个队都没过,何等罪过啊 T_T

题目意思很简单,两个人石头剪刀布,一个人的出法是确定的,另一个人的出法有一定约束,某两次要相同或者不同,问你第二个人能否全部都不失败。题目还是很容易想到2-sat的,不过按照官方题解里说的每次出拳拆分成两个相对点的建图方法相当麻烦,小明哥按照那种方法建图就写了5k那么长,比较容易理解的方法是拆六个点:

石头(R), 非石头(~R)

布(P), 非布(~P)

剪刀(S), 非剪刀(~S)

每次只能三者取一个,那么就是如果出了一个,另外两个就不能出

R->~P, R->~S, P->~R, P->~S, S->~R, S->~P

然后根据对方的出法,就只能出平局和胜局两种出法

比如:如果对方是石头(R),那么只能出R和P,非R即P,非P即R

~R->P, ~P->R

最后就是加入约束关系,如果两次必须相同:

R1<->R2, P1<->P2, S1<->S2 均是双向边

如果不同也是一样

R1->~R2, R2->~R1, ......

这样建好图之后跑一边2-sat模板就能A掉了

比赛时候模板敲错,查了三个多小时,还好最后A掉,不然就去卧轨了 T_T

  1 #include<cstdio>  2 #include<cstring>  3 #include<algorithm>  4 using namespace std;  5 #define N 60005  6 #define M 999999  7   8 struct Edge{  9     int vtx,next; 10 }E[M]; 11 int head[N],size; 12 int dfn[N],low[N],blg[N],step,scc; 13 int stk[N],top; 14 bool ins[N]; 15  16 void Init(){ 17     memset(head,-1,sizeof(head)); 18     memset(dfn,-1,sizeof(dfn)); 19     memset(ins,false,sizeof(ins)); 20     step=size=0; top=-1; 21 } 22  23 void Insert(int u,int v){ 24     E[size].vtx=v; 25     E[size].next=head[u]; 26     head[u]=size++; 27 } 28  29 void Tarjan(int u){ 30     stk[++top]=u; ins[u]=true; 31     dfn[u]=low[u]=step++; 32     for(int i=head[u];~i;i=E[i].next){ 33         int v=E[i].vtx; 34         if(dfn[v]==-1){ 35             Tarjan(v); 36             low[u]=min(low[u],low[v]); 37         }else if(ins[v]){ 38             low[u]=min(low[u],dfn[v]); 39         } 40     } 41     if(low[u]==dfn[u]){ 42         for(int v=-1;v!=u;top--){ 43             v=stk[top]; 44             ins[v]=false; 45             blg[v]=scc; 46         } 47         scc++; 48     } 49 } 50  51 int main(){ 52     int t,cas=0; 53     scanf("%d",&t); 54     while(t--){ 55         int n,m; 56         scanf("%d%d",&n,&m); 57          58         Init(); 59         for(int i=0;i<n;i++){ 60             Insert(i*6+0,i*6+3); 61             Insert(i*6+0,i*6+5); 62             Insert(i*6+2,i*6+1); 63             Insert(i*6+2,i*6+5); 64             Insert(i*6+4,i*6+1); 65             Insert(i*6+4,i*6+3); 66         } 67          68         for(int i=0;i<n;i++){ 69             int v; 70             scanf("%d",&v); 71             if(v==1){ 72                 Insert(i*6+3,i*6+0); 73                 Insert(i*6+1,i*6+2); 74             }else if(v==2){ 75                 Insert(i*6+5,i*6+2); 76                 Insert(i*6+3,i*6+4); 77             }else if(v==3){ 78                 Insert(i*6+5,i*6+0); 79                 Insert(i*6+1,i*6+4); 80             } 81         } 82         for(int i=0;i<m;i++){ 83             int a,b,v; 84             scanf("%d%d%d",&a,&b,&v); 85             a--; b--; 86             if(v){ 87                 Insert(a*6+0,b*6+1); 88                 Insert(a*6+2,b*6+3); 89                 Insert(a*6+4,b*6+5); 90              91                 Insert(b*6+0,a*6+1); 92                 Insert(b*6+2,a*6+3); 93                 Insert(b*6+4,a*6+5); 94             }else{ 95                 Insert(a*6+0,b*6+0); 96                 Insert(a*6+2,b*6+2); 97                 Insert(a*6+4,b*6+4); 98              99                 Insert(b*6+0,a*6+0);100                 Insert(b*6+2,a*6+2);101                 Insert(b*6+4,a*6+4);102             }103         }104         for(int i=0;i<n*6;i++){105             if(dfn[i]==-1) Tarjan(i);106         }107         bool flag=true;108         for(int i=0;i<n*3;i++){109             if(blg[i<<1]==blg[i<<1|1]){110                 flag=false;111                 break;112             }113         }114         115         printf("Case #%d: ",++cas);116         puts(flag?"yes":"no");117     }118 }

两个点的建图方法也很容易理解,每一次只有两种出法,平局或是胜局,即如果对方是S,那么只能是R或者P,R和P是两个相对点,这样就省去了上面方法中的前两种建图。不过这时要记下对应的两个点是什么,然后建图就要讨论很多很多东西了:

比如说如果两次分别是RP1和SP2,两次必须相同时候建图

第一次有P,第二次也有P,那么第一个P和第二个P变为强连通,P1<->P2

第一次有R,第二次没R,那么就是R->P1,表示这种情况不可能

S同样,S->P2建边,不可能存在的情况

各种情况讨论下去,然后做强连通

这样做时间和内存都会少很多,但是代码量大了很多,对于O(n+m)的这种算法作用不大...

转载于:https://www.cnblogs.com/ambition/archive/2011/11/09/Eliminate_the_Conflict.html

HDU 4115 Eliminate the Conflict【2011 ACM Asia Chengdu Regional Problem E】相关推荐

  1. HDU 4115 Eliminate the Conflict(2-sat)

    HDU 4115 Eliminate the Conflict 题目链接 题意:Alice和Bob这对狗男女在玩剪刀石头布.已知Bob每轮要出什么,然后Bob给Alice一些限制,1表示i轮和j轮Al ...

  2. HDU 4115 Eliminate the Conflict(2-sat 判解存在性)

    题意: 有两个人玩一个石头剪刀布的游戏,两个人连续玩N轮,给出其中一个人的N轮出的情况和该人对另外一个人的一些限制条件,有两种限制:每种限制表示为:(a,b,c) ,如果c==0 则表示该人对另外一个 ...

  3. HDU 1175 连连看【2011年11月14号更新】

    [url]http://acm.hdu.edu.cn/showproblem.php?pid=1175[/url] [size=medium]Problem Description "连连看 ...

  4. HDU 1166 敌兵布阵 【线段树-点修改--计算区间和】

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  5. 天健医院信息化系统资料汇总【2011年5月20日更新】

    论坛中天健的资料大家非常喜欢,下载量一般都比较高,由于论坛资源越来越多(现在已经将近4万)大家找起来也比较麻烦,所以我将天健医院信息化系统的相关资料整理一下,方便大家查找自己需要的内容. 天健医疗信息 ...

  6. HDU 1285--确定比赛名次【拓扑排序 amp;amp; 邻接表实现】

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  7. 【SDUT第11周周赛Problem A】SDUT2576——Queen Collisions

    来源:点击打开链接 由于一些原因,需要在短短的一段时间内速成图论和搜索了=  =,希望能够有一个不错的结果. 这个题是著名八皇后问题的变种,大意就是问在一个棋盘中,照面的皇后有几组(横着竖着斜着都算) ...

  8. 2011 ACM 0和1思想

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2011 题意:求1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + ...前n项的和. 思路 ...

  9. [2-sat专练]poj 3683,hdu 1814,hdu 1824,hdu 3622,hdu 4115,hdu 4421

    文章目录 Priest John's Busiest Day code Peaceful Commission code Let's go home code Bomb Game code Elimi ...

最新文章

  1. webhook php自动部署,git利用webhook实现自动部署​
  2. 计算机应用基础本科常见问题讨论,《计算机应用基础》(本科)2017年6月期末考试指导.pdf...
  3. 使用bash echo 输出回车转义
  4. 更新整理本人所有博文中提供的代码与工具(C++,2013.11)
  5. Struts1和Struts2的区别和对比(完整版)(转)
  6. 数据库 数据库SQL语句五
  7. 安装“消息队列 (MSMQ)”
  8. mysql 时间 设计模式_数据库时间设计模式
  9. Turn to Stone
  10. 心电信号matlab电路仿真实例,基于matlab的心电信号分析系统的设计与仿真.docx
  11. 清华大学计算机系哪个专业就业前景最好,往年清华大学就业前景最好的专业
  12. 角度换算数字在线计算机,角度换算成数字(计算器数字转角度换算)
  13. php汉字utf8编码转换,PHP UTF8编码内的繁简转换类
  14. Android studio 录屏并制作gif
  15. 投影仪与计算机连接方式,【投影网教程】投影仪连接电脑的方法
  16. SYN 包在什么场景下会被丢弃?
  17. ECC椭圆曲线加密的特点以及在有限域(Fp)的三点共线问题
  18. linux系统mysql报err1055_MySQL Err 1055的解决
  19. 使用UltraISO从文件还原Linux操作系统ISO
  20. C++ 制作简易音乐播放器

热门文章

  1. UnityShader28:噪声纹理
  2. OpenGL基础36:天空盒
  3. HDU 5934 2016CCPC杭州 B: Bomb(Trajan强连通)
  4. os.path.basename()
  5. opencv 学习第二课 摄像头、外部视频读取、处理、显示、写入 代码注释版 保证你每一行都能读懂
  6. java解析xml文件:创建、读取、遍历、增删查改、保存
  7. shell的简单应用
  8. print (re.findall((?:abc)+,abcabcabc))
  9. 2016北京集训测试赛(十三) Problem B: 网络战争
  10. Testing a React+Redux web application