题目链接

题意看这吧。。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. 基于Python的机器学习实战:AadBoost

    目录: 1. Boosting方法的简介 2. AdaBoost算法 3.基于单层决策树构建弱分类器 4.完整的AdaBoost的算法实现 5.总结 1. Boosting方法的简介 返回目录 Boo ...

  2. Excel中快捷键Ctrl+End覆盖过多

    Sub dd() MsgBox ActiveSheet.UsedRange.Address End Sub 更简单的方法:通过快捷键,选中空白行/列,然后删除行/列,保存,OK!

  3. PHP框架CodeIgniter--URL去除index.php

    今天学习CodeIgniter简称CI的第一天,记录下学习心得. CI中国https://codeigniter.org.cn/user_guide/general/urls.html?highlig ...

  4. python httplib和urllib的性能比较

    httplib代码: urlParseResult = urlparse(url) host = urlParseResult.hostname path = urlParseResult.path ...

  5. MyEclipse中将项目的编码从默认GBK改变为默认UTF-8

  6. Ex 5_21 无向图G=(V,E)的反馈边集..._第九次作业

    根据题意,求的是最大生成树.利用Kruskal算法,对边进行从大到小的顺序进行排序,然后再依次取出边加入结果集中.假设图有n个顶点,那么,当结果集中有n-1条边时,剩下的边的集合即为反馈边集. pac ...

  7. 在Mac上安装GTK(go语言GUI)

    1.在终端输入:xcode-select --install 安装command line工具, 如果安装了Xcode, 就直接跳过该步骤 2. 在终端输入:ruby -e "$(curl ...

  8. 详解Android属性动画

    前面我们讲到的属性动画都是使用代码的定义方式:Android属性动画之ValueAnimator和Android属性动画之ObjectAnimator和AnimatorSet,下面我们再来看看使用XM ...

  9. Quartz 定时邮件发送多个备份文件

    项目代码 pom.xml 文件Quartz 的包是整个项目不可缺少的 <properties> <!-- Spring的版本 --> <springframework.v ...

  10. CF126B

    CF126B Password 题意: 给出一个字符串 H,找一个最长的字符串 h,使得它既作为前缀出现过.又作为后缀出现过.还作为中间的子串出现过. 解法: 沿着 $ next_n $ 枚举字符串, ...