poj 3648 2-SAT问题
思路:将每对夫妻看成是对立状态,每个不正常关系都是一个矛盾,按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问题的更多相关文章
- 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 2-sat
题目大意: 有一对新人结婚,邀请n对夫妇去参加婚礼. 有一张很长的桌子,人只能坐在桌子的两边,还要满 足下面的要求:1.每对夫妇不能坐在同一侧 2.n对夫妇 之中可能有通奸关系(包括男男,男女,女女) ...
- POJ 3648 Wedding (2-SAT,经典)
题意:新郎和新娘结婚,来了n-1对夫妻,这些夫妻包括新郎之间有通奸关系(包括男女,男男,女女),我们的目地是为了满足新娘,新娘对面不能坐着一对夫妻,也不能坐着有任何通奸关系的人,另外新郎一定要坐新娘对 ...
- poj 1687 Buggy Sat 简单计算几何
暑期集训出的第一道一血 感觉自己萌萌哒…… 这道题本身并没有坑点 仅仅是翻译巨坑…… 解大腿在做B 安学长在做E 我闲着也没事 就一个词一个词翻译F…… 最后感觉…… 题干大多数都看不懂…… 也都没啥 ...
- POJ 3648 Wedding
2-SAT,直接选择新娘一侧的比较难做,所以处理的时候选择新郎一侧的,最后反着输出就可以. A和B通奸的话,就建边 A->B'以及B->A’,表示 A在新郎一侧的话,B一定不在:B在新郎一 ...
- poj 3648 2-SAT建图+topsort输出结果
其实2-SAT类型题目的类型比较明确,基本模型差不多是对于n组对称的点,通过给出的限制条件建图连边,然后通过缩点和判断冲突来解决问题.要注意的是在topsort输出结果的时候,缩点后建图需要反向连边, ...
- 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对人有通奸关系,对于这一对人,不能同时坐在新娘对面(新娘新郎也可能和别人有通奸关系).求如何避免冲突 ...
随机推荐
- thymeleaf中的th:with用法
局部变量,th:with能定义局部变量: <div th:with="firstPer=${persons[0]}"> <p> The name of th ...
- sublime text2 用ctags插件实现方法定位
sublime text2 用ctags插件实现方法定位(转) 我们用sublime几乎都会首先安装这个插件,这个插件是管理插件的功能,先安装它,再安装其他插件就方便了. 点击sublime的菜单栏 ...
- ASP.NET中身份验证的三种方法
Asp.net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活.Forms 验证方式对基于用户的验证授权 ...
- LCA + 二分(倍增)
两个最近的点u和v的最近的公共的祖先称为最近公共祖先(LCA).普通的LCA算法,每算一次LCA的时间复杂度为线性o(n); 这里讲LCA + 二分的方法.首先对于任意的节点v,利用其父节点的信息,可 ...
- [转]Oracle 操作字符串的函数
转至:http://yedward.net/?id=62 (1)oracle中实现截取字符串:substr substr(string, start_position, [length]) 其中,st ...
- XML操作:1.XML类(http://blog.csdn.net/happy09li/article/details/7460521)
XML绑定TreeView private void XmlOperation_Load(object sender, EventArgs e) { path = AppDomain.CurrentD ...
- setbuffer和freopen做一个简单的日志组件
目标场景是这样的: 多线程的应用程序要频繁打一些小字节的日志,也不想引用很重的日志库. 设想了一个极其简单的日志组件,main线程中重定向stdout到文件,同时setbuffer设置一个10k的缓冲 ...
- cloudstack 修改显示名称
http://192.168.153.245:8900/client/api?command=updateVirtualMachineid=922d15e1-9be0-44ac-9494-ce5afc ...
- java中动态代理
一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...
- 通过java发送http请求
通常的http请求都是由用户点击某个连接或者按钮来发起的,但是在一些后台的Java程序中需要发送一些get或这post请求,因为不涉及前台页面,该怎么办呢? 下面为大家提供一个Java发送http请求 ...