思路:将每对夫妻看成是对立状态,每个不正常关系都是一个矛盾,按2-SAT的方式建边。最后建一条新娘到新郎的边。具体看注释

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<queue>
  6. #define Maxn 62
  7. #define Maxm Maxn*Maxn
  8. using namespace std;
  9. int vi[Maxn],head[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,id[Maxn],Stack[Maxn],in[Maxn],Hash[Maxn],col[Maxn];
  10. struct Edge{
  11. int u,v,next;
  12. }edge[Maxm];
  13. void init()//初始化
  14. {
  15. memset(vi,,sizeof(vi));
  16. memset(head,-,sizeof(head));
  17. memset(dfn,,sizeof(dfn));
  18. memset(low,,sizeof(low));
  19. memset(id,,sizeof(id));
  20. memset(in,,sizeof(in));
  21. memset(col,,sizeof(col));
  22. e=lab=top=num=;
  23. }
  24. void add(int u,int v)//加边
  25. {
  26. edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
  27. }
  28. void Tarjan(int u)//找出强连通分支
  29. {
  30. int i,j,v;
  31. dfn[u]=low[u]=++lab;
  32. Stack[top++]=u;
  33. vi[u]=;
  34. for(i=head[u];i!=-;i=edge[i].next)
  35. {
  36. v=edge[i].v;
  37. if(!dfn[v])
  38. {
  39. Tarjan(v);
  40. low[u]=min(low[u],low[v]);
  41. }
  42. if(vi[v])
  43. low[u]=min(low[u],dfn[v]);
  44.  
  45. }
  46. if(low[u]==dfn[u])
  47. {
  48. ++num;
  49. do{
  50. i=Stack[--top];
  51. vi[i]=;
  52. id[i]=num;
  53. }while(i!=u);
  54. }
  55. }
  56. void buildGraphic()//缩点后重新建树,以便进行拓扑排序
  57. {
  58. int ed=e,u,v;
  59. memset(head,-,sizeof(head));
  60. e=;
  61. int i;
  62. for(i=;i<ed;i++)
  63. {
  64. u=edge[i].u;
  65. v=edge[i].v;
  66. if(id[u]!=id[v])
  67. {
  68. add(id[v],id[u]);//由于2-SAT问题中是找出度为0的点,这里我们建个反图,方便进行拓扑排序,变成找入度为0的点
  69. in[id[u]]++;
  70. }
  71. }
  72. }
  73. void Topsort()
  74. {
  75. int i,j,u,v,temp;
  76. queue<int> q;
  77. int fron,rear;
  78. fron=rear=;
  79. for(i=;i<=num;i++)
  80. if(in[i]==)
  81. q.push(i);
  82. while(!q.empty())
  83. {
  84. temp=q.front();
  85. q.pop();
  86. if(!col[temp]) col[temp]=,col[Hash[temp]]=;//如果该连通分支未着色,那么给他着1,它的对立点就必须着不同的色
  87. for(i=head[temp];i!=-;i=edge[i].next)
  88. {
  89. v=edge[i].v;
  90. in[v]--;
  91. if(in[v]==)
  92. q.push(v);
  93. }
  94. }
  95. }
  96. int solve()
  97. {
  98. int i,j;
  99. for(i=;i<=*n;i++)
  100. if(!dfn[i])
  101. Tarjan(i);
  102. for(i=;i<=n;i++)
  103. if(id[i]==id[i+n])
  104. return ;//有矛盾则结束
  105. else
  106. Hash[id[i]]=id[i+n],Hash[id[i+n]]=id[i];//标记每个连通分支间的对立关系,即不能再同一侧
  107.  
  108. buildGraphic();
  109. Topsort();
  110. for(i=;i<=n;i++)
  111. if(col[id[i]]==col[id[n+]]) printf("%dh ",i-);//输出和新娘同侧的人
  112. else printf("%dw ",i-);
  113. printf("\n");
  114. return ;
  115. }
  116. int op(int x)
  117. {
  118. if(x<=n) return x+n;
  119. return x-n;
  120. }
  121. int main()
  122. {
  123. int m,i,j,a,b;
  124. char c1,c2;
  125. while(scanf("%d%d",&n,&m),n|m)
  126. {
  127. init();
  128. for(i=;i<m;i++)
  129. {
  130. scanf("%d%c%d%c",&a,&c1,&b,&c2);//husband点为1~N,wife点为N+1~2*N
  131. a++,b++;
  132. if(c1=='w')
  133. a+=n;
  134. if(c2=='w')
  135. b+=n;
  136. add(a,op(b));
  137. add(b,op(a));
  138. }//我们的目标是选择和新郎同一侧的,新郎固然在自己一侧。
  139. add(n+,);//建一条由新娘到新郎的边,若选择了新娘,新郎也会被选,新郎和新娘成了同侧,便矛盾。即新娘不能和新郎同一侧
  140. if(!solve())
  141. printf("bad luck\n");
  142. }
  143. return ;
  144. }

poj 3648 2-SAT问题的更多相关文章

  1. POJ 3648 Wedding(2-SAT的模型运用+DFS | Tarjan)

    Wedding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10427   Accepted: 3170   Specia ...

  2. poj 3648 Wedding 2-SAT问题入门题目

    Description Up to thirty couples will attend a wedding feast, at which they will be seated on either ...

  3. POJ 3648 2-sat

    题目大意: 有一对新人结婚,邀请n对夫妇去参加婚礼. 有一张很长的桌子,人只能坐在桌子的两边,还要满 足下面的要求:1.每对夫妇不能坐在同一侧 2.n对夫妇 之中可能有通奸关系(包括男男,男女,女女) ...

  4. POJ 3648 Wedding (2-SAT,经典)

    题意:新郎和新娘结婚,来了n-1对夫妻,这些夫妻包括新郎之间有通奸关系(包括男女,男男,女女),我们的目地是为了满足新娘,新娘对面不能坐着一对夫妻,也不能坐着有任何通奸关系的人,另外新郎一定要坐新娘对 ...

  5. poj 1687 Buggy Sat 简单计算几何

    暑期集训出的第一道一血 感觉自己萌萌哒…… 这道题本身并没有坑点 仅仅是翻译巨坑…… 解大腿在做B 安学长在做E 我闲着也没事 就一个词一个词翻译F…… 最后感觉…… 题干大多数都看不懂…… 也都没啥 ...

  6. POJ 3648 Wedding

    2-SAT,直接选择新娘一侧的比较难做,所以处理的时候选择新郎一侧的,最后反着输出就可以. A和B通奸的话,就建边 A->B'以及B->A’,表示 A在新郎一侧的话,B一定不在:B在新郎一 ...

  7. poj 3648 2-SAT建图+topsort输出结果

    其实2-SAT类型题目的类型比较明确,基本模型差不多是对于n组对称的点,通过给出的限制条件建图连边,然后通过缩点和判断冲突来解决问题.要注意的是在topsort输出结果的时候,缩点后建图需要反向连边, ...

  8. POJ.3648.Wedding(2-SAT)

    题目链接 题意看这吧..https://www.cnblogs.com/wenruo/p/5885948.html \(Solution\) 每对夫妇只能有一个坐在新娘这一边,这正符合2-SAT初始状 ...

  9. POJ - 3648 Wedding (2-SAT 输出解决方案)

    题意:有N-1对夫妇和1对新郎新娘要出席婚礼,这N对人要坐在走廊两侧.要求每对夫妇要坐在不同侧.有M对人有通奸关系,对于这一对人,不能同时坐在新娘对面(新娘新郎也可能和别人有通奸关系).求如何避免冲突 ...

随机推荐

  1. 【C语言】-循环的嵌套

    循环的嵌套:当在一个循环语句中嵌入另一个循环时,成为循环的嵌套. 循环嵌套的形式: (1)for语句中嵌入for语句: for ( ) { for ( ) { ... } } (2)for语句嵌入wh ...

  2. nyoj 203 三国志(最短路加01背包)

    三国志 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 <三国志>是一款很经典的经营策略类游戏.我们的小白同学是这款游戏的忠实玩家.现在他把游戏简化一下, ...

  3. linux系统中如何查看日志 (常用命令)

    cat tail -f 日 志 文 件 说 明 /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安全相关 ...

  4. cookie.js 加载顺序问题

    今天遇到一个问题,在使用cookie.js时,只有在jquery.js文件后加载整体才有效 有效加载顺序 <head> <script type="text/javascr ...

  5. UI进阶 动画

    前言:所谓动画,即应用界面上展示的各种过渡效果,不过其实没有动画并不影响我们产品的功能实现 一.动画 1.动画可以达到的效果 传达状态 提高用户对直接操作的感知 帮助用户可视化操作的结果 2.使用动画 ...

  6. 怎么删除windows中无用的服务

    搜索cmd->以管理员身份打开 输入sc delete  服务名 回车即可

  7. Andoird Studio 错误: 非法字符: '\ufeff' 解决方案。

    从网上下载一个安卓UI模板,导入到AndroidStudio的时候提示MainActivity非法字符: '\ufeff' 解决方案,细细一想编译器没报错,但编译出错,应该是隐蔽字符BOM的问题,于是 ...

  8. python flask 部署

    flask在开发的时候,经常启动本身进行调试(本身可以设置监听的端口,例如 在app.run(port=8088),当然默认不设置端口为5000). 但生产环境经常使用uswgi充当flask的宿主, ...

  9. Middleware课程01-概述

    中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源.中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯.是连接两个独立应用程序或独立系统的软件.相 ...

  10. delphi array应用 DayOfWeek星期几判断

    //array应用 DayOfWeek星期几判断 procedure TForm1.Button1Click(Sender: TObject);var    days:array[1..7] of s ...