POJ 3648 Wedding (2-SAT,经典)
题意:新郎和新娘结婚,来了n-1对夫妻,这些夫妻包括新郎之间有通奸关系(包括男女,男男,女女),我们的目地是为了满足新娘,新娘对面不能坐着一对夫妻,也不能坐着有任何通奸关系的人,另外新郎一定要坐新娘对面。但是输出时输出坐在新娘这一边的人(不需要输出新娘)。
分析:
问题只是要求不能 “通奸对” 不能同时出现在新娘对面(即新郎那边),这个必须考虑到2*n个人的座位问题。一开始以为只考虑女的怎么坐就行了,男肯定坐对面,但是后来想这样子只能保证两边都没有通奸对出现,不符合题意,有些数据过不了。
考虑数据大小,2*n个人,那么数组要开4*n大小,每个人都有两个选择,尽管一对夫妻必须对着坐。
不如假设新娘一定坐在左边,即 i*2+1这边,那么新郎必定在j*2了,可以通过(j*2+1)->(j*2)控制新郎位置,新娘同理。 而我们要选择的是没有冲突的一个解,则要按照这个去构造与新郎同边的人的情况不冲突。当接到一条通奸边u-v时,应该是有边 u*2 -> v*2+1和 v*2 -> u*2+1 。注意这只是控制新郎这边的。除了这些边之外,每对夫妻之间也有个硬性要求是,必须对着坐,所以要给这n对夫妻一些固定的边,将他们绑定在一起。
挑选出一组解之后,其中i*2+1的就是解了,但是这也有n*2个人,我们只要n个,其中有一半和新娘同颜色的才是答案,剩下n人。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <stack>
#include <algorithm>
#include <map>
//#include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
vector<int> vect[N]; int col[N], s[N], c;
bool color(int x)
{
if(col[x^]) return false;
if(col[x]) return true;
col[x]=;
s[c++]=x;
for(int i=; i<vect[x].size(); i++)
if(!color(vect[x][i])) return false;
return true;
} int cal(int n)
{
memset(col,,sizeof(col));
memset(s,,sizeof(s));
for(int i=; i<n; i+=)
{
if(!col[i] && !col[i+])
{
c=;
if(!color(i))
{
while(c) col[s[--c]]=; //清除这次错误的路径
if(!color(i+)) return false; //再试试
}
}
}
return true;
} void print(int n)
{
int t=col[];
for(int i=; i<n; i+=) //新娘一定坐在i*2+1这边
{
if(col[i]) //再排除掉一半人。
{
if(i%==) printf("%dw ",i/);
else printf("%dh ",i/);
}
}
printf("\n");
} int main()
{
freopen("input.txt", "r", stdin);
int n, m, a, c;
char b, d;
while(scanf("%d%d",&n,&m), n+m)
{
for(int i=n*; i>=; i--) vect[i].clear(); //2*30个人,要120个大小 for(int i=; i<n*; i++ ) //先解决老婆与老公之间的边。老婆是偶数。
{
vect[i*].push_back((i^)*+);
vect[i*+].push_back((i^)*);
}
// 先固定好新郎新娘的位置
vect[*+].push_back(*); //保证新郎一定坐在i*2这边
vect[*].push_back(*+); //保证新娘一定坐在i*2+1这边 for(int i=; i<m; i++) //不能只考虑n个女人怎么坐
{
scanf("%d%c %d%c", &a, &b, &c, &d);
if(a==c) continue; //夫妇肯定对着坐,不用管 a<<=; //恢复它们的真正号数
c<<=;
if(b=='h') a++;
if(d=='h') c++; vect[a*].push_back(c*+); //如果你坐新郎那边,我必须坐对面了。但是你坐新娘那边,我也可以坐,不冲突。
vect[c*].push_back(a*+); //如果我坐新郎那边,你必须坐对面了
} if(!cal(n*)) puts("bad luck");
else print(n*);
}
return ;
}
AC代码
下面是摘自别人的分析:
很明显的2-sat模型,虽然要输出新娘这一边的人,但是我们构建的是对面的,为什么?因为我们要保证对面的人没有矛盾(但是新娘这一侧是允许有矛盾的,因为新娘看不到她这一侧的人)。另外我们要保证新郎一定坐在对面,在2-sat中固定一个元素的a的方法是~a->a,这个也好理解,a和~a必须选一个,如果选了a那么就选了,如果选了~a,又因为~a->a,说明a也必须选,也就是说无论如何a都要被选到。
按照2-sat正常的流程坐下来,会得到一个可行解,也就是和新郎颜色相同的点,它们都是可行解,它们是没有矛盾的,可以坐在新娘对面,所以剩下的点(其实就是和新娘同色的点)就是和新娘坐在一侧的。
POJ 3648 Wedding (2-SAT,经典)的更多相关文章
- POJ 3648 Wedding(2-SAT的模型运用+DFS | Tarjan)
Wedding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10427 Accepted: 3170 Specia ...
- poj 3648 Wedding 2-SAT问题入门题目
Description Up to thirty couples will attend a wedding feast, at which they will be seated on either ...
- POJ 3648 Wedding
2-SAT,直接选择新娘一侧的比较难做,所以处理的时候选择新郎一侧的,最后反着输出就可以. A和B通奸的话,就建边 A->B'以及B->A’,表示 A在新郎一侧的话,B一定不在:B在新郎一 ...
- POJ.3648.Wedding(2-SAT)
题目链接 题意看这吧..https://www.cnblogs.com/wenruo/p/5885948.html \(Solution\) 每对夫妇只能有一个坐在新娘这一边,这正符合2-SAT初始状 ...
- POJ - 3648 Wedding (2-SAT 输出解决方案)
题意:有N-1对夫妇和1对新郎新娘要出席婚礼,这N对人要坐在走廊两侧.要求每对夫妇要坐在不同侧.有M对人有通奸关系,对于这一对人,不能同时坐在新娘对面(新娘新郎也可能和别人有通奸关系).求如何避免冲突 ...
- poj 3648 Wedding【2-SAT+tarjan+拓扑】
看错题*n,注意是输出新娘这边的-- 按2-SAT规则连互斥的边,然后注意连一条(1,1+n)表示新娘必选 然后输出color[belong[i]]==color[belong[1+n(新娘)]]的点 ...
- 【POJ】3648 Wedding
http://poj.org/problem?id=3648 题意:n对人(编号0-n-1,'w'表示第一个人,'h'表示第二个人),每对两个,人坐在桌子两侧.满足:1.每对人中的两个人不能坐在同一侧 ...
- Wedding (poj 3648 2-SAT 输出随意一组解)
Language: Default Wedding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9004 Accept ...
- POJ 3678 Katu Puzzle (经典2-Sat)
Katu Puzzle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6553 Accepted: 2401 Descr ...
随机推荐
- Linux学习1
Linux中一切皆文件,且不依靠扩展名区分文件,学习Linux必须要熟悉在字符界面进行文件的管理. 首先是Linux的查询命令. (1)ls -a是显示当前目录所有文件,包含隐藏文件,如图中文件名前加 ...
- ADO和ADO.NET的区别
1. ADO与ADO.NET简介 ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立 ...
- Nagios脚本编写事例
目标:编写一个简单的nagios脚本,实现监控client上的nginx进程是否启动,假如没启动的话发出报警. 首先在master上对nagios的配置文件进行设置,修改services.cfg文件, ...
- 【转】用perl写的单位电脑信息采集程序
perl,后来我又改过了增加了一些交互和数据库检测的功能.主要用于收集ip.mac.姓名.房间,后来又加入了维修记录的功能.服务器端接受数据并存入数据库中. 代码如下: 主要用于收集ip.mac.姓名 ...
- Git之不明觉厉11-利其器source tree
前面10篇文章都在用命令行,虽然装逼不错,但是我想说一句,平时我也是用source tree比较多点,命令行一般都是在source tree的图形按钮找不到在哪里,就直接用命令行.对于初次用git的同 ...
- 【面试题】Https
https原理, 我很难一下子记住, https=http+ssl 先说http, 基于tcp/IP协议 传输,有三次握手 http://blog.csdn*net/xubo_zhang/art ...
- iOS开发(1) WebView和HTML 显示
iOS 7 已经release了.现在学习iOS开发还是非常热门的.到处也有些团队在寻找iOS开发的人才. 那么,iOS开发.....省略了1万字.... HTML5 +CSS3+JS...再省略1万 ...
- 【Linux】设定一个能输入中文的英文环境!
引子:centos startx 进入桌面后使用中文输入法 这个解决方法太蠢了,而且只适用于centos等red系系统... 在此提供一个更加通用的方法 => 只要设置好系统的locale坏境变 ...
- Xcode 向6.0以后版本添加iOS开发空白模板
打开finder,找到应用程序,找到xcode 右键显示包内容.按照如下目录进行查找:Contents ▸ Developer ▸ Platforms ▸ iPhoneOS.platform ▸ De ...
- 李洪强iOS开发之【零基础学习iOS开发】【02-C语言】06-变量与内存
在前面一节中简单介绍了变量的使用,当我们定义一个变量的时候,系统就会为变量分配一块存储空间.而变量的数值在内存中是以二进制的形式存储的,这讲来深入研究变量在内存中的一些存储细节. 一.字节和地址 为了 ...