poj 3648 2-SAT建图+topsort输出结果
其实2-SAT类型题目的类型比较明确,基本模型差不多是对于n组对称的点,通过给出的限制条件建图连边,然后通过缩点和判断冲突来解决问题。要注意的是在topsort输出结果的时候,缩点后建图需要反向连边,然后输出就可以了。2-sat题型差不多。
题意:新娘新郎分别坐在长桌两边,n-1队夫妇来参加婚礼,要求:夫妇不能坐在同一边,通奸关系不能坐在同一边。输出新娘对面的序列。
思路:对称关系:夫妇,限制条件:通奸关系。基础2-sat问题,缩点找冲突topsort输出结果一气呵成。。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 2002
int instack[MAXN],stack[MAXN],fa[MAXN],vis[MAXN],head[MAXN],first[MAXN];
int dfn[MAXN],low[MAXN],in[MAXN],ans[MAXN],que[MAXN];
int a[MAXN][2],b[MAXN][2],flag[MAXN],cf[MAXN],col[MAXN];
int n,m,tot,scnt,time,tt,top,index; struct Edge
{
int v,next;
}edge[MAXN*MAXN],e[MAXN*MAXN]; void addedge(int u,int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void adde(int u,int v)
{
e[tt].v=v;
e[tt].next=first[u];
first[u]=tt++;
}
void tarjan(int u)
{
instack[u]=1;
stack[top++]=u;
dfn[u]=low[u]=++index;
int v;
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
scnt++;
do
{
v=stack[--top];
instack[v]=0;
fa[v]=scnt;
}while(v!=u);
}
}
void build()
{
for(int i=0;i<m;i++) //2*n的点
{
int t1,t2;char c,v;
scanf("%d%c",&t1,&c);
scanf("%d%c",&t2,&v);
if(c=='h'&&v=='h')
{
addedge(t1+n,t2);
addedge(t2+n,t1);
}
else if(c=='h'&&v=='w')
{
addedge(t1+n,t2+n);
addedge(t2,t1);
}
else if(c=='w'&&v=='h')
{
addedge(t1,t2);
addedge(t2+n,t1+n);
}
else if(c=='w'&&v=='w')
{
addedge(t1,t2+n);
addedge(t2,t1+n);
}
}
addedge(0,n);
}
void solve()
{
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
index=0;scnt=0;top=0;
for(int i=0;i<2*n;i++)
{
if(!dfn[i])
tarjan(i);
}
}
int check()
{
for(int i=0;i<n;i++)
{
if(fa[i]==fa[i+n]) //冲突
{
return 0;
}
cf[fa[i]]=fa[i+n];
cf[fa[i+n]]=fa[i];
}
return 1;
}
void topsort()
{
int head=1,tail=1;
for(int i=1;i<=scnt;i++)
{
if(in[i]==0)
{
que[tail++]=i;
}
}
int v;
while(tail>head)
{
int u=que[head];
head++;
if(col[u]==0) //对于未着色的点x,将x染成红色1,同时将与x矛盾的点cf[x]染成蓝色-1。
{
col[u]=1;
col[cf[u]]=-1;
}
for(int i=first[u];i!=-1;i=e[i].next)
{
v=e[i].v;
if(--in[v]==0)
{
que[tail++]=v;
}
}
}
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
{
if(col[fa[i]]==1)
{
ans[i]=1;
}
}
for(int i=1;i<n;i++)
{
if(ans[i])
printf("%dh ",i);
else
printf("%dw ",i);
}
printf("\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF,(n||m))
{
memset(head,-1,sizeof(head));tot=0;
memset(first,-1,sizeof(first));tt=0; build();
solve();
if(!check())printf("bad luck\n");
else
{
memset(in,0,sizeof(in));
memset(col,0,sizeof(col));
for(int i=0;i<2*n;i++)
{
int v;
for(int j=head[i];j!=-1;j=edge[j].next)
{
v=edge[j].v;
if(fa[i]!=fa[v])
{
adde(fa[v],fa[i]);
in[fa[i]]++;
}
}
}
topsort();
}
}
return 0;
}
poj 3648 2-SAT建图+topsort输出结果的更多相关文章
- poj 3281 最大流+建图
很巧妙的思想 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html 本题能够想到用最大流做,那真的是太绝了.建模的方法很 ...
- POJ 1637 Sightseeing tour 建图+网络流
题意: 给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路. 分析: 存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即 ...
- POJ 1149 网络流 合并建图
这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独 ...
- POJ - 1149 PIGS (建图思维+最大流)
(点击查看原题) 题目分析 (以下均为 Edelweiss 大佬的思路,博主承认自己写不了这么好,但是学习的心促使我记录下这个好题的写法,所以代码是我写的) [题目大意] 有 M 个猪圈,每个猪圈里初 ...
- poj 3281 最大流建图
题目链接:http://poj.org/problem?id=3281 #include <cstdio> #include <cmath> #include <algo ...
- [poj 3281]最大流+建图很巧妙
题目链接:http://poj.org/problem?id=3281 看了kuangbin大佬的思路,还用着kuangbin板子orz http://www.cnblogs.com/kuangb ...
- POJ 1161 Walls ( Floyd && 建图 )
题意 : 在某国,城市之间建起了长城,每一条长城连接两座城市.每条长城互不相交.因此,从一个区域到另一个区域,需要经过一些城镇或者穿过一些长城.任意两个城市A和B之间最多只有一条长城,一端在A城市, ...
- POJ 2226 缩点建图+二分图最大匹配
这个最小覆盖但不同于 POJ 3041,只有横或者竖方向连通的点能用一块板子覆盖,非连续的,就要用多块 所以用类似并查集方法,分别横向与竖向缩点,有交集的地方就连通,再走一遍最大匹配即可 一开始还有点 ...
- POJ 2374 线段树建图+Dijkstra
题意: 思路: 线段树+Dijkstra(要堆优化的) 线段树要支持打标记 一个栅栏 拆成两个点 :左和右 新加一个栅栏的时候 看看左端点有没有被覆盖过 如果有的话 就分别从覆盖的那条线段的左右向当前 ...
随机推荐
- 微信客户端+微信公众平台+新浪云SAE+Arduino+WS100(控制LED)
第一步:准备 1.智能手机微信客户端或微信电脑版 2.注册微信公众平台 https://mp.weixin.qq.com 3.注册新浪账号 http://www.sinacloud.com 4.拥有一 ...
- offsetWidth\offsetleft 等图文解释
网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offs ...
- little bird
LITTLE BIRD Bzoj 3831 相对而言是一道比较简单的DP,不过它需要用单调队列优化.首先是朴素O(n2), if(d[j]>f[i]) f[i]=min(f[i],f[j]); ...
- PyCharm中光标变粗的解决方法
pycharm中光标变粗,如下: 原因:光标进入了改写状态. 解决方法:按一下键盘中的Insert键就好了.
- NYOJ 23.取石子(一)
取石子(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 一天,TT在寝室闲着无聊,和同寝的人玩起了取石子游戏,而由于条件有限,他/她们是用旺仔小馒头当作石子.游 ...
- NO.1-M2
一,CSS盒模型 1,当父盒子包裹子盒子,且上边线重合时,给子盒子添加margin-top时,子盒子与父盒子的上边线并不能分开,,而是导致,两个盒子同时下来,而是导致,两个盒子同时下来 使两条上边 ...
- 扩展Python模块系列(三)----参数解析与结果封装
在上一节中,通过一个简单的例子介绍了C语言扩展Python内建模块的整体流程,从本节开始讲开始深入讨论一些细节问题,在细节讨论中从始至终都会涉及[引用计数]的问题.首先讨论C语言封装的Python函数 ...
- 010.Controller methods and views --【控制器方法与视图】
Controller methods and views 控制器方法与视图 2017-3-7 9 分钟阅读时长 作者 By Rick Anderson We have a good start to ...
- Jquery ztree树插件2
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- MySQL多字节字符集造成主从数据不一致问题
MySQL多字节字符集造成主从数据不一致问题 来自江羽 2013-04-27 16:03:56| 分类: 默认分类|举报|字号 订阅 转载: http://backend.blog.163.co ...