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对人有通奸关系,对于这一对人,不能同时坐在新娘对面(新娘新郎也可能和别人有通奸关系).求如何避免冲突 ...
随机推荐
- 【C语言】-循环的嵌套
循环的嵌套:当在一个循环语句中嵌入另一个循环时,成为循环的嵌套. 循环嵌套的形式: (1)for语句中嵌入for语句: for ( ) { for ( ) { ... } } (2)for语句嵌入wh ...
- nyoj 203 三国志(最短路加01背包)
三国志 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 <三国志>是一款很经典的经营策略类游戏.我们的小白同学是这款游戏的忠实玩家.现在他把游戏简化一下, ...
- linux系统中如何查看日志 (常用命令)
cat tail -f 日 志 文 件 说 明 /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安全相关 ...
- cookie.js 加载顺序问题
今天遇到一个问题,在使用cookie.js时,只有在jquery.js文件后加载整体才有效 有效加载顺序 <head> <script type="text/javascr ...
- UI进阶 动画
前言:所谓动画,即应用界面上展示的各种过渡效果,不过其实没有动画并不影响我们产品的功能实现 一.动画 1.动画可以达到的效果 传达状态 提高用户对直接操作的感知 帮助用户可视化操作的结果 2.使用动画 ...
- 怎么删除windows中无用的服务
搜索cmd->以管理员身份打开 输入sc delete 服务名 回车即可
- Andoird Studio 错误: 非法字符: '\ufeff' 解决方案。
从网上下载一个安卓UI模板,导入到AndroidStudio的时候提示MainActivity非法字符: '\ufeff' 解决方案,细细一想编译器没报错,但编译出错,应该是隐蔽字符BOM的问题,于是 ...
- python flask 部署
flask在开发的时候,经常启动本身进行调试(本身可以设置监听的端口,例如 在app.run(port=8088),当然默认不设置端口为5000). 但生产环境经常使用uswgi充当flask的宿主, ...
- Middleware课程01-概述
中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源.中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯.是连接两个独立应用程序或独立系统的软件.相 ...
- delphi array应用 DayOfWeek星期几判断
//array应用 DayOfWeek星期几判断 procedure TForm1.Button1Click(Sender: TObject);var days:array[1..7] of s ...