http://poj.org/problem?id=3648

(在家,而且因为2-SAT写的不明不白的,所以这篇详细写)

题目大意:

有一对新人结婚,邀请了n-1 对夫妇去参加婚礼。婚礼上所有人要坐在一张很长的桌子的两边。所有的夫妇不能坐在同一边。还有m 对人,这对人不能同时坐在新郎一边,但可以同时坐在新娘这边或是分两边坐

以这道题为2-SAT讲解模板题。

(请先了解2-SAT是干什么的再往下看)

首先判断:打眼一看一定是2-SAT。

然后建图,a到b表示如果选了a就一定选b的意思

那么对于我们所给出的矛盾关系,发现a和b虽然不共边,但是a一定和b的另一半共边或着b一定和a的另一半共边。于是利用上面的定义加边。

这里假设k为妻子,k+n为丈夫。

有一个需要加的就是(0,0+n)需要加边(难点)

为什么呢?因为我们能够发现,只有新郎一边是不能冲突的,新娘一边随意,那么加上这条边时如果我们取了新娘就一定会取新郎而导致错误,所以程序一定会去选择新郎,由此我们得到了新郎那边的座次。在那之后全部相反就能获得新娘的座次了。

关键的2-SAT判冲突:

首先tarjan缩点,如果相互为夫妻的人在同一个强连通分量里就说明错误。

然后按照拓扑序我们有:(以(a,b)为一对冲突为例,取a表示a与新郎共边)

如果a所在的强连通分量(新图中的点)的拓扑序在b(非a)所在的强连通分量之后,则a为真。(显然取b就得取a而冲突,但是取a就可以不用取b避免冲突)

但是我们能够发现Tarjan 算法所求的强连通分量就是按拓扑序的逆序得出的,所以我们直接用编号来表示,并不需要真的去拓扑……

举个例子,比如这道题,明显i与i+n冲突,to[i]表示i缩点编号,那我们有:

to[i]<to[i+n]时取i,反之取i+n。

但是这是新郎侧编号,为了求新娘侧的人,我们把上面的条件颠倒一下即可。

(PS:此题输入有毒,如果不断RE请原模原样参照路由器的代码的读入写,你就明白数据有什么问题了)

#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;const int N=;
const int M=;
struct node{
int to;
int nxt;
}edge[M*];
int head[N*],dfn[N*],low[N*],to[N*];
int n,m,t,l,cnt;
bool instack[N*];
stack<int>q;
inline void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
inline int neg(int x){
if(x<=n)return x+n;
return x-n;
}
void tarjan(int u){
t++;
dfn[u]=t;
low[u]=t;
q.push(u);
instack[u]=;
for(int i=head[u];i!=;i=edge[i].nxt){
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
int v;
l++;
do{
v=q.top();
q.pop();
instack[v]=;
to[v]=l;
}while(v!=u);
}
return;
}
inline void clr(){
cnt=;t=;l=;
memset(dfn,,sizeof(dfn));
memset(head,,sizeof(head));
return;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF&&(n>||m>)){
clr();
for(int i=;i<=m;i++){
int u,v;char a,b;
scanf("%d%c %d%c",&u,&a,&v,&b);
u++;v++;
if(a=='h')u+=n;
if(b=='h')v+=n;
add(u,neg(v));
add(v,neg(u));
}
add(,n+);
for(int i=;i<=n*;i++){
if(!dfn[i])tarjan(i);
}
bool flag=;
for(int i=;i<=n;i++){
if(to[i]==to[i+n]){
flag=;
break;
}
}
if(!flag){
printf("bad luck\n");
continue;
}
for(int i=;i<=n;i++){
printf("%d",i-);
if(to[i]>to[i+n])printf("w ");
else printf("h ");
}
printf("\n");
}
return ;
}

(敲了半个小时的同时搞懂了2-SAT,同时凌晨的城市真好看,好累……)

POJ3648:Wedding——题解(配2-SAT简易讲解)的更多相关文章

  1. POJ3648 Wedding 【2-sat】

    题目 Up to thirty couples will attend a wedding feast, at which they will be seated on either side of ...

  2. poj3648 Wedding

    Wedding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10975   Accepted: 3355   Specia ...

  3. POJ-3648 Wedding 2sat

    题目链接:http://poj.org/problem?id=3648‘ 题意:一对情人举行婚礼,有n对夫妇参加,别人对着坐在一个长桌子的两边,新娘和新郎坐在最后面,新娘只能看见坐在他对面的人.现在, ...

  4. substring和substr、$.extend()、$.fn.extend()、(function($){….})(jQuery)的简易讲解

    1.    JS中substring与substr的区别 Substring: 该方法可以有一个参数也可以有两个参数. l  一个参数: 示例: var str="Olive": ...

  5. webpack打包vue -->简易讲解

    ### 1. 测试环境: 推荐这篇文章:讲的很细致 https://www.cnblogs.com/lhweb15/p/5660609.html 1. webpack.config.js自行安装 { ...

  6. P5035金坷垃题解(快速幂的讲解)

      首先经过读题,我们发现找到合格的金坷垃,怎么样的金坷垃才是合格的呢?(我们不难发现1肯定是合格的[题目已经给出了]) 然后我们开始手推一下之后合格的金坷垃: 2-1=1(合格) 3-1-1=1(不 ...

  7. 《算法详解:C++11语言描述》已出版

    经过漫长的编写.修订和印刷过程,书籍<算法详解:C++11语言描述>终于出版了!目前本书已在各大电商平台上架,搜索书名即可找到对应商品.本书的特色在于: 介绍最新的C++11.C++14和 ...

  8. labview入门到出家11(补充)——基于单片机和labview开发的虚拟示波器

    ​ 之前有小伙伴提到需要虚拟示波器的资料,有些库还有文件丢失了,直接给的工程跑不起来,这里我把关键的地方讲解一下,大家可以自行开发.其实开发不难,只是有些点会耗点时间.虚拟示波器,顾名思义就是非实物的 ...

  9. 【手把手】JavaWeb 入门级项目实战 -- 文章发布系统 (第十二节)

    好的,那么在上一节中呢,评论功能的后台已经写好了,这一节,先把这部分后台代码和前台对接一下. 1.评论功能实现 我们修改一下保存评论按钮的点击事件,用jQuery的方式获取文本框中的值,然后通过aja ...

随机推荐

  1. Wireshark对HTTPS数据的解密

    本文来自网易云社区 之前有介绍<wireshark抓包分析--TCP/IP协议>,然后某天有人问我,示例里是HTTP的,如果是HTTPS,你可以抓包分析吗?基于好奇,我查阅了下相关资料,把 ...

  2. hadoop 家族图

    hadoop家族

  3. hdu2509Be the Winner(反nim博弈)

    Be the Winner Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  4. TW实习日记:第31-32天

    不知不觉的,实习的净工作天数,已经都超过一个月了.因为对工作内容不是很满意,所以打算月底离职,也不知道是公司太缺人还是我真的能干活,领导竟然三番两次找我让我再考虑...明天又要找我了,哎...随机应变 ...

  5. 银行系统ps:不太完善,蟹蟹评论

    # 主程序运行 import time from guanli import GuanLi from atm import ATM from user import User def main(): ...

  6. 372. Delete Node in a Linked List【LintCode java】

    Description Implement an algorithm to delete a node in the middle of a singly linked list, given onl ...

  7. 百度翻译api 实现简易微信翻译小程序

    介绍 口袋翻译 口袋翻译 微信小程序 翻译功能 含7类语言的相互翻译 包含最近10条的翻译历史回溯功能 微信搜索:简e翻译 功能展示   使用百度翻译api需要申请 appid 与 key 并在 ap ...

  8. Java开发中用的比较多的数据结构

    java 中几种常用数据结构 2016年07月11日 09:11:27 阅读数:83211 标签: 数据结构java 更多 个人分类: 自行学习   JAVA中常用的数据结构(java.util. 中 ...

  9. Halcon10 下载

    Halcon10 下载地址:http://www.211xun.com/download_page_1.html HALCON 10 是一套机器视觉图像处理库,由一千多个算子以及底层的数据管理核心构成 ...

  10. Java 单例模式探讨

    以下是我再次研究单例(Java 单例模式缺点)时在网上收集的资料,相信你们看完就对单例完全掌握了 Java单例模式应该是看起来以及用起来简单的一种设计模式,但是就实现方式以及原理来说,也并不浅显哦. ...