POJ 3648 2-sat

题目大意:

有一对新人结婚,邀请n对夫妇去参加婚礼。
有一张很长的桌子,人只能坐在桌子的两边,还要满
足下面的要求:1.每对夫妇不能坐在同一侧 2.n对夫妇
之中可能有通奸关系(包括男男,男女,女女),有通
奸关系的不能同时坐在新娘的对面,可以分开坐,可以
同时坐在新娘这一侧。如果存在一种可行的方案,输出
与新娘同侧的人。

这里因为输入的是字符串,要注意的是数字可能不只是一个个位数,要

while(isdigit(s1[index1])) i = i*10+(s1[index1++]-‘0‘);
while(isdigit(s2[index2])) j = j*10+(s2[index2++]-‘0‘);

这里自己一直没找到原因,错了很多次

其他的就按照 2i 表示 i 号丈夫坐在新娘对面,2i+1 表示i 号妻子坐在新娘对面

初始将新郎对应的编号的标记设为true , 因为他必然坐在新娘对面

这样找下来,最后标记为false的便是坐在新娘这边的

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <ctype.h>
 5 #include <algorithm>
 6 using namespace std;
 7 #define N 300
 8 int n , m , S[N] , c ;
 9 bool mark[N];
10 char s1[10] , s2[10];
11 vector<int> G[N];
12
13 void init()
14 {
15     memset(mark , 0 , sizeof(mark));
16     for(int i=0 ; i<n*2 ; i++) G[i].clear();
17 }
18
19 bool dfs(int u)
20 {
21     if(mark[u]) return true;
22     if(mark[u^1]) return false;
23     mark[u] = true;
24     S[c++] = u;
25     for(int i=0 ; i<G[u].size() ; i++)
26         if(!dfs(G[u][i])) return false;
27     return true;
28 }
29
30 bool solve()
31 {
32     mark[0] = true;//一定是坐在新娘对面,所以新郎为true
33     for(int i=0 ; i<2*n ; i+=2){
34         if(!mark[i] && !mark[i^1]){
35             c = 0;
36             if(!dfs(i)){
37                 while(c) mark[S[--c]] = false;
38                 if(!dfs(i^1)) return false;
39             }
40         }
41     }
42     return true;
43 }
44
45 void add_clause(int i , int p , int j , int q)
46 {
47     int m = 2*i+p , n = 2*j+q;
48     G[m].push_back(n^1);
49     G[n].push_back(m^1);
50 }
51
52 int main()
53 {
54    // freopen("in.txt" , "r" , stdin);
55     while(scanf("%d%d" , &n , &m) , n+m)
56     {
57         init();
58         while(m--){
59             scanf("%s%s" , s1 , s2);
60             int i , j , p , q;
61             i = 0 , j = 0;
62             int index1 = 0 , index2 = 0;
63             while(isdigit(s1[index1])) i = i*10+(s1[index1++]-‘0‘);
64             while(isdigit(s2[index2])) j = j*10+(s2[index2++]-‘0‘);
65             p = s1[index1]==‘h‘?0:1 , q = s2[index2]==‘h‘?0:1;
66             add_clause(i , p , j ,q);
67         }
68         if(!solve()) puts("bad luck");
69         else{
70             int flag = 0;
71             for(int i=2 ; i<n*2 ; i++){
72                 if(!mark[i]){
73                     if(flag) printf(" %d%c" , i/2 , i&1?‘w‘:‘h‘);
74                     else printf("%d%c" , i/2 , i&1?‘w‘:‘h‘);
75                     flag=1;
76                 }
77             }
78             puts("");
79         }
80     }
81     return 0;
82 }
时间: 2024-10-28 12:51:27

POJ 3648 2-sat的相关文章

POJ 3648 Wedding (2-SAT+输出可行解)

题目地址:POJ 3648 这题终于AC了....没有专门对新郎新娘加一条边.. 这题前面一直读错题意了,调试了好长时间样例也没过..这题的意思是只要新郎那一边没有通奸的就可以,然后输出新娘那一边的人. 然后就是对那些有**关系的加边,由于新郎新娘必须要在两侧,所以最后要额外加一条边.然后用强连通判断,逆拓扑染色输出可行解即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include

POJ 3648 Wedding(2-SAT 拓扑排序输出任意一种解决方案)

题目链接:http://poj.org/problem?id=3648 Description Up to thirty couples will attend a wedding feast, at which they will be seated on either side of a long table. The bride and groom sit at one end, opposite each other, and the bride wears an elaborate h

poj 3648 Wedding 2-SAT问题入门题目

Description Up to thirty couples will attend a wedding feast, at which they will be seated on either side of a long table. The bride and groom sit at one end, opposite each other, and the bride wears an elaborate headdress that keeps her from seeing

poj 3648 Wedding

每对夫妻恰有一人坐在新娘对面,两个关系不正常的人不能都在新娘对面 问,是否有解 #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector> #include&

UVA 11294 POJ 3648 Wedding

题意: 婚礼上新郎新娘坐在桌子两侧  新娘只能看见对面的人  已知一些人有XX关系-  新娘不想看见有关系的同时坐在对面  问  满足条件的情况下  新娘这边做的人是谁 思路: 新郎那一边的约束最多  有利于解题  那么就变成了  一个人要不要坐新郎这边的2-sat问题  因此可以先求新郎这边的人  然后反一下就是新娘这边的了  注意  新郎是必选点  而且  不能选和新郎有XX关系的- 代码: #include<cstdio> #include<cstring> #include

Wedding (poj 3648 2-SAT 输出随意一组解)

Language: Default Wedding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9004   Accepted: 2722   Special Judge Description Up to thirty couples will attend a wedding feast, at which they will be seated on either side of a long table. Th

poj 1687 Buggy Sat 简单计算几何

暑期集训出的第一道一血 感觉自己萌萌哒…… 这道题本身并没有坑点 仅仅是翻译巨坑…… 解大腿在做B 安学长在做E 我闲着也没事 就一个词一个词翻译F…… 最后感觉…… 题干大多数都看不懂…… 也都没啥用…… 大概呢…… 就是给你n个点…… m条回路…… 问你哪条回路是最外面的…… 总之最后就是让你求哪个回路组成的图形面积最大…… 考点就是多边形面积公式…… 怕有误差就没加/2…… 好像加了也能过吧…… WA了两次 一次是选错点了 一次是第一个点和最后一个点顺序反了…… 1 #include<st

2-SAT问题

2-SAT问题 现有一个由N个布尔值组成的序列A,给出一些限制关系,比如A[x]AND A[y]=0.A[x] OR A[y] OR A[z]=1等,要确定A[0..N-1]的值,使得其满足所有限制关系.这个称为SAT问题,特别的,若每种限制关系中最多只对两个元素进行限制,则称为2-SAT问题. 由于在2-SAT问题中,最多只对两个元素进行限制,所以可能的限制关系共有11种: A[x] NOT A[x] A[x] AND A[y] A[x] AND NOT A[y] A[x] OR A[y] A

【图论】2-sat总结

2-sat总结 2-sat问题,一般表现的形式为.每一个点有两种方式a,b,要么选a,要么选b.而且点点之间有一些约束关系.比如:u和v至少一个选a.那么这就是一个表达式.把a当成真,b当成假,那就是u真或v真.2-sat的题目就是这样.给定这些约束,推断是否会矛盾 注意表达式的转化形式,(事实上就是离散数学中那几种转换方式) 比方(u真且v真)或(u假且v假)就能够转化成(u真或v假)且(u假或v真),这样就能建立关系 2-sat中的原理,事实上和2染色是一样的,把每一个结点拆分成一个真结点和