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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define Maxn 62
#define Maxm Maxn*Maxn
using namespace std;
int vi[Maxn],head[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,id[Maxn],Stack[Maxn],in[Maxn],Hash[Maxn],col[Maxn];
struct Edge{
int u,v,next;
}edge[Maxm];
void init()//初始化
{
memset(vi,,sizeof(vi));
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(id,,sizeof(id));
memset(in,,sizeof(in));
memset(col,,sizeof(col));
e=lab=top=num=;
}
void add(int u,int v)//加边
{
edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
}
void Tarjan(int u)//找出强连通分支
{
int i,j,v;
dfn[u]=low[u]=++lab;
Stack[top++]=u;
vi[u]=;
for(i=head[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
if(vi[v])
low[u]=min(low[u],dfn[v]); }
if(low[u]==dfn[u])
{
++num;
do{
i=Stack[--top];
vi[i]=;
id[i]=num;
}while(i!=u);
}
}
void buildGraphic()//缩点后重新建树,以便进行拓扑排序
{
int ed=e,u,v;
memset(head,-,sizeof(head));
e=;
int i;
for(i=;i<ed;i++)
{
u=edge[i].u;
v=edge[i].v;
if(id[u]!=id[v])
{
add(id[v],id[u]);//由于2-SAT问题中是找出度为0的点,这里我们建个反图,方便进行拓扑排序,变成找入度为0的点
in[id[u]]++;
}
}
}
void Topsort()
{
int i,j,u,v,temp;
queue<int> q;
int fron,rear;
fron=rear=;
for(i=;i<=num;i++)
if(in[i]==)
q.push(i);
while(!q.empty())
{
temp=q.front();
q.pop();
if(!col[temp]) col[temp]=,col[Hash[temp]]=;//如果该连通分支未着色,那么给他着1,它的对立点就必须着不同的色
for(i=head[temp];i!=-;i=edge[i].next)
{
v=edge[i].v;
in[v]--;
if(in[v]==)
q.push(v);
}
}
}
int solve()
{
int i,j;
for(i=;i<=*n;i++)
if(!dfn[i])
Tarjan(i);
for(i=;i<=n;i++)
if(id[i]==id[i+n])
return ;//有矛盾则结束
else
Hash[id[i]]=id[i+n],Hash[id[i+n]]=id[i];//标记每个连通分支间的对立关系,即不能再同一侧 buildGraphic();
Topsort();
for(i=;i<=n;i++)
if(col[id[i]]==col[id[n+]]) printf("%dh ",i-);//输出和新娘同侧的人
else printf("%dw ",i-);
printf("\n");
return ;
}
int op(int x)
{
if(x<=n) return x+n;
return x-n;
}
int main()
{
int m,i,j,a,b;
char c1,c2;
while(scanf("%d%d",&n,&m),n|m)
{
init();
for(i=;i<m;i++)
{
scanf("%d%c%d%c",&a,&c1,&b,&c2);//husband点为1~N,wife点为N+1~2*N
a++,b++;
if(c1=='w')
a+=n;
if(c2=='w')
b+=n;
add(a,op(b));
add(b,op(a));
}//我们的目标是选择和新郎同一侧的,新郎固然在自己一侧。
add(n+,);//建一条由新娘到新郎的边,若选择了新娘,新郎也会被选,新郎和新娘成了同侧,便矛盾。即新娘不能和新郎同一侧
if(!solve())
printf("bad luck\n");
}
return ;
}

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. 提高iOS开发效率的方法和工具

    http://www.cocoachina.com/ios/20150717/12626.html 介绍 这篇文章主要是介绍一下我在iOS开发中使用到的一些可以提升开发效率的方法和工具. IDE 首先 ...

  2. 用鼠标右键选择DataGridView单元格或行

    在datagirdview_cellmousedown事件中先将CurrentCell(或CurrentRow)的Selected属性设为false,然后将鼠标右键点击的单元格(或行)设为Curren ...

  3. 字串数_hdu_1261(大数极致).java

    字串数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  4. sqlserver表分区与调优与行列转换

    转自: http://www.cnblogs.com/knowledgesea/p/3696912.html http://www.open-open.com/lib/view/open1418462 ...

  5. mongodb 、nosql、 redis、 memcached 是什么?

    mongodb 是一个基于文档的数据库,所有数据是从磁盘上进行读写的.MongoDB善长的是对无模式JSON数据的查询.而Redis是一个基于内存的键值数据库,它由C语言实现的,与Nginx/ Nod ...

  6. 在VS中安装EF和项目引用EF

    1.通过Visual Studio安装NuGet (1). 打开Visual Studio扩展管理器     (2). 选择联机库,并在搜索中写入NuGet,然后点击搜索结果中NuGet Packag ...

  7. PHP linux spl_autoload_register区分大小写

    一个PHP脚本用到spl_autoload_register,在WINDOWS下运行正常,但在LINUX就include不了,后来发现WINDOWS大小写不敏感,而在LINUX下区分大小写,WINDO ...

  8. Invoke-Express 执行多个批处理命令的函数

    function Mult_ping ($ips) { # $cmdline = "PIng" foreach ($ip in $ips) { $cmdline = "p ...

  9. 关于Vim的问题s

    2013-11-23 17:29:45 1.关于.swp文件 swap对于保护非正常退出是有好处的,但从最开始使用vim就发现的一个问题十分恼火!非正常退出再进入后选择了恢复R,然后编辑正常保存正常退 ...

  10. URAL 1779 F - The Great Team 构造

    F - The Great TeamTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...