题目链接

题意看这吧。。https://www.cnblogs.com/wenruo/p/5885948.html

\(Solution\)

每对夫妇只能有一个坐在新娘这一边,这正符合2-SAT初始状态

若以0表示新娘,以1表示新郎

那么对于有关系的u,v(i'表示在新娘一侧),应该连边u->v',v->u',而不是用i'表示新娘对面(新郎一侧),而连边u'->v,v'->u

因为如果新郎与v有关系,就会连边1(u')->v',这成了同在新郎一侧了;但若新娘与v有关系,连边0(u)->v'(同在新娘一侧)是符合连边规则的

有矛盾的情况是有关系的两人同在新娘对面,所以2-SAT求出的可行解是新娘对面的

新娘与新郎要坐在两侧,连边0->1,表示不能选0,一定选1,这样选出来的解就是新娘对面了

每对夫妇就是对立的,也不分性别。。所以随便一个表示i,另一个就表示i'

输出方案时只要输出与新娘染色相同的就可以了

是bel[i]还是i不要混 注意与新郎新娘标号统一

总是有点想不明白。。

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=5005,M=1e5+5; int n,m,Enum,H[N],nxt[M],to[M],sk[N],top,cnt,bel[N],low[N],dfn[N],id;
int num,head[N],snxt[N],sto[N],conf[N],dgr[N]/*indgree*/,col[N],q[N];//conflict
bool ins[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v){
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
}
inline void AddEdge2(int u,int v){
++dgr[v], sto[++num]=v, snxt[num]=head[u], head[u]=num;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++id, sk[++top]=x, ins[x]=1;
for(int v,i=H[x]; i; i=nxt[i])
if(!dfn[v=to[i]]) Tarjan(v), low[x]=std::min(low[x],low[v]);
else if(ins[v]) low[x]=std::min(low[x],dfn[v]);
if(low[x]==dfn[x])
{
++cnt;
do{
bel[sk[top]]=cnt, ins[sk[top--]]=0;
}while(x!=sk[top+1]);
}
}
bool Topo()
{
for(int i=0; i<n<<1; i+=2)
if(bel[i]==bel[i^1]) return 0;
else conf[bel[i]]=bel[i^1],conf[bel[i^1]]=bel[i];
num=0, memset(head,0,sizeof head),
memset(col,0,sizeof col), memset(dgr,0,sizeof dgr);
for(int x=0; x<n<<1; ++x)
for(int i=H[x]; i; i=nxt[i])
if(bel[x]!=bel[to[i]]) AddEdge2(bel[to[i]],bel[x]);
int h=0,t=0;
for(int i=1; i<=cnt; ++i)
if(!dgr[i]) q[t++]=i;
while(h<t)
{
int x=q[h++];
if(!col[x]) col[x]=1,col[conf[x]]=2;
for(int i=head[x]; i; i=snxt[i])
if(!--dgr[sto[i]]) q[t++]=sto[i];
}
return 1;
} int main()
{
while(n=read(),m=read(),n&&m)
{
id=top=cnt=Enum=0, memset(H,0,sizeof H);
memset(dfn,0,sizeof dfn);
char c,d; int a,b,s,t;
while(m--)
{
scanf("%d%c %d%c",&a,&c,&b,&d);
// s= c=='h'?a<<1:a<<1|1;//WA:这表示的man是2a,但是新郎也是man 是2a+1=1
s= c=='w'?a<<1:a<<1|1;
t= d=='w'?b<<1:b<<1|1;
AddEdge(s,t^1), AddEdge(t,s^1);
}
AddEdge(0,1);
for(int i=0; i<n<<1; ++i)
if(!dfn[i]) Tarjan(i);
if(Topo())
{
for(int i=1; i<n; ++i)
if(col[bel[i<<1]]==1) printf("%dh ",i);
else printf("%dw ",i);
putchar('\n');
}
else puts("bad luck");
}
return 0;
}

POJ.3648.Wedding(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 Wedding (2-SAT,经典)

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

  4. POJ 3648 Wedding

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

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

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

  6. poj 3648 Wedding【2-SAT+tarjan+拓扑】

    看错题*n,注意是输出新娘这边的-- 按2-SAT规则连互斥的边,然后注意连一条(1,1+n)表示新娘必选 然后输出color[belong[i]]==color[belong[1+n(新娘)]]的点 ...

  7. 【POJ】3648 Wedding

    http://poj.org/problem?id=3648 题意:n对人(编号0-n-1,'w'表示第一个人,'h'表示第二个人),每对两个,人坐在桌子两侧.满足:1.每对人中的两个人不能坐在同一侧 ...

  8. Wedding (poj 3648 2-SAT 输出随意一组解)

    Language: Default Wedding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9004   Accept ...

  9. Map Labeler POJ - 2296(2 - sat 具体关系建边)

    题意: 给出n个点  让求这n个点所能建成的正方形的最大边长,要求不覆盖,且这n个点在正方形上或下边的中点位置 解析: 当然是二分,但建图就有点还行..比较难想..行吧...我太垃圾... 2 - s ...

随机推荐

  1. 【PE结构】由浅入深PE基础学习-菜鸟手动查询导出表、相对虚拟地址(RVA)与文件偏移地址转换(FOA)

    0 前言 此篇文章想写如何通过工具手查导出表.PE文件代码编程过程中的原理.文笔不是很好,内容也是查阅了很多的资料后整合出来的.希望借此加深对PE文件格式的理解,也希望可以对看雪论坛有所贡献.因为了解 ...

  2. ORB feature(O for orientation)

    参考链接:http://blog.csdn.net/yang843061497/article/details/38553765 绪论 假如我有2张美女图片,我想确认这2张图片中美女是否是同一个人.这 ...

  3. Python3学习笔记12-定义函数及调用

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段,能提高应用的模块性,和代码的重复利用率 Python提供了许多内建函数,比如print().也可以自己创建函数,这被叫做用户自定义函数 ...

  4. 出现“error LNK1169: 找到一个或多个多重定义的符号”的原因

    或许,有人真的会这样写程序吧...所以才会碰到如下哥们提出的问题. https://zhidao.baidu.com/question/131426210.html 出现这种问题的原因链接中的最佳答案 ...

  5. Oracle数据库操作基本语法

    创建表 SQL>create table classes(        classId number(2),        cname varchar2(40),        birthda ...

  6. 关于ftp上传changeWorkingDirectory()方法的路径切换问题

    在上传时 FTPClient提供了upload方法,对于upload(file,path)的第二个参数path ,上传到哪里的这个路径, ftp是利用changeWorkingDirectory()方 ...

  7. 一台电脑,两个及多个git账号配置

    1. 生成两[三]个ssh公钥私钥 方法参照:http://www.cnblogs.com/fanbi/p/7772812.html第三步骤 假定其中一个是id_rsa, 另一个时id_rsa_two ...

  8. 560. Subarray Sum Equals K

    Given an array of integers and an integer k, you need to find the total number of continuous subarra ...

  9. Android Menu用法全面讲解

    说明:本文只介绍Android3.0及以上的Menu知识点. 菜单的分类 菜单是Android应用中非常重要且常见的组成部分,主要可以分为三类:选项菜单.上下文菜单/上下文操作模式以及弹出菜单.它们的 ...

  10. Jmeter NonGUI模式

    一般情况下我们都是在NonGUI模式下运行jmeter.这样做有两个好处 节省系统资源,能够产生更大的负载 可以通过命令行参数对测试场景进行更精细的配置 示例 创建luzhi.jmx脚本 jmeter ...