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对人有通奸关系,对于这一对人,不能同时坐在新娘对面(新娘新郎也可能和别人有通奸关系).求如何避免冲突 ...
随机推荐
- HDU 4891 The Great Pan (模拟)
The Great Pan 题目链接: http://acm.hust.edu.cn/vjudge/contest/123554#problem/D Description As a programm ...
- Spring MVC MultiActionController example
In Spring MVC application, MultiActionController is used to group related actions into a single cont ...
- #c word转换PDF
需要引用Microsoft.Office.Interop.Word,版本是07之上的. 这个版本会判断文件是否被占用. using Microsoft.Office.Interop.Word; usi ...
- keil中编译时出现*** ERROR L107: ADDRESS SPACE OVERFLOW
解决方法: http://zhidao.baidu.com/link?url=DWTVVdALVqPtUt0sWPURD6c1eEppyu9CXocLTeRZlZlhwHOA1P1xdesqmUQNw ...
- UIImageView旋转任意角度
-(UIImageView *) makeRotation:(UIImageView *)image speedX:(float)X speedY:(float)Y { // 头文件中需要定义 ...
- Unity3D中关于场景销毁时事件调用顺序的一点记录
先说一下我遇到的问题,我弄了一个对象池管理多个对象,对象池绑定在一个GameObject上,每个对象在OnBecameInvisible时会进行回收(即移出屏幕就回收),但是当场景切换或停止运行程序时 ...
- CLR探索应用程序域世界(上):Windbg SOS剖析揭示域世界
在CLR的世界中,有一系列的令人Amazing的技术和架构.其中,CLR对应用程序在内存中内存分配,执行模型,程序之间的交互等一系列的技术,值得每一个致力于DotNet平台的技术人员深究. 编程人员在 ...
- [c++]堆和栈的区别
堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...
- Rstudio编辑界面美化设置
美化Rstudio的编辑界面有利于我们输入代码,合适的调整更是减少错误. 可以根据自己的喜好和习惯选择.
- Date、String、Calendar、Timestamp类型之间的转化
1.Calendar 转化 String Calendar calendat = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDa ...