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. pg 与 oracle 比较

    所谓动态引擎,就是说比如有很多张表的Join,原始的做法是一开始就生成好这个执行计划,随后执行,但实际上很多表Join的时候,你一开始生成的那个执行计划很有可能是不对的. 那么动态执行计划就是指它可以 ...

  2. andriod 学习三 使用android资源

    3.1 android框架中有许多资源,包括布局,字符串,位图,图片....,使用资源之前需要在相应的资源文件中定义资源,然后编译程序时ADT将定义的资源转换成java类并给予唯一的id,而代码中需要 ...

  3. 「LeetCode」0002-Longest Substring Without Repeating Characters(C++)

    分析 贪心思想.注意更新每次判断的最长不同子串的左区间的时候,它是必须单调增的(有时候会在这里翻车). 代码 关掉流同步能有效提高速度. static const auto io_sync_off = ...

  4. 「专题训练」Air Raid(HDU-1151)

    题目 在一个城市里有\(n\)个地点和\(k\)条道路,道路是无环的(也就是说一定可以二分染色--回路长度为偶数0),现在伞兵需要去n个地点视察,只能沿着路的方向走,问最少需要多少伞兵. 分析 这是什 ...

  5. maven 安装、配置

    简介: maven 大大提高项目开发速度     编译---打包---测试--安装   一条龙 maven将项目构建的过程标准化,每一个阶段使用一个命令完成,下面是构建过程一些阶段 清理 mvn cl ...

  6. Ubuntu16.04安装truffle时的一些错误

    1.使用truffle时出现 Error: /usr/bin/env: node: 没有那个文件或目录 1.如果是用sudo apt-get install nodejs命令安装的nodejs, ub ...

  7. truffle运行特殊 无法找到module的处理方法

    https://blog.csdn.net/SnWJy/article/details/80549227 错误描述: ​ truffle项目根目录执行truffle compile时,报错'modul ...

  8. 系统滴答定时器(SysTick)中断配置

    系统滴答定时器(SysTick)中断配置 在STM32标准库中是通过SysTick_Config()函数配置时钟中断的,然后SysTick_Handler()函数自动定时触发其中的函数. if(Sys ...

  9. php+原生ajax实现图片文件上传功能实例

    html+js 代码 <!DOCTYPE html> <html> <head> <title>Html5 Ajax 上传文件</title> ...

  10. Python中的global和nonlocal

    在Python中,一个变量的scope范围从小到大分成4部分:Local Scope(也可以看成是当前函数形成的scope),Enclosing Scope(简单来说,就是外层函数形成的scope), ...