您的位置:首页 > 其它

POJ 3648 2-sat

2015-07-28 10:40 218 查看
题目大意:

有一对新人结婚,邀请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的便是坐在新娘这边的

#include <cstdio>
#include <cstring>
#include <vector>
#include <ctype.h>
#include <algorithm>
using namespace std;
#define N 300
int n , m , S
, c ;
bool mark
;
char s1[10] , s2[10];
vector<int> G
;

void init()
{
memset(mark , 0 , sizeof(mark));
for(int i=0 ; i<n*2 ; i++) G[i].clear();
}

bool dfs(int u)
{
if(mark[u]) return true;
if(mark[u^1]) return false;
mark[u] = true;
S[c++] = u;
for(int i=0 ; i<G[u].size() ; i++)
if(!dfs(G[u][i])) return false;
return true;
}

bool solve()
{
mark[0] = true;//一定是坐在新娘对面,所以新郎为true
for(int i=0 ; i<2*n ; i+=2){
if(!mark[i] && !mark[i^1]){
c = 0;
if(!dfs(i)){
while(c) mark[S[--c]] = false;
if(!dfs(i^1)) return false;
}
}
}
return true;
}

void add_clause(int i , int p , int j , int q)
{
int m = 2*i+p , n = 2*j+q;
G[m].push_back(n^1);
G
.push_back(m^1);
}

int main()
{
// freopen("in.txt" , "r" , stdin);
while(scanf("%d%d" , &n , &m) , n+m)
{
init();
while(m--){
scanf("%s%s" , s1 , s2);
int i , j , p , q;
i = 0 , j = 0;
int index1 = 0 , index2 = 0;
while(isdigit(s1[index1])) i = i*10+(s1[index1++]-'0');
while(isdigit(s2[index2])) j = j*10+(s2[index2++]-'0');
p = s1[index1]=='h'?0:1 , q = s2[index2]=='h'?0:1;
add_clause(i , p , j ,q);
}
if(!solve()) puts("bad luck");
else{
int flag = 0;
for(int i=2 ; i<n*2 ; i++){
if(!mark[i]){
if(flag) printf(" %d%c" , i/2 , i&1?'w':'h');
else printf("%d%c" , i/2 , i&1?'w':'h');
flag=1;
}
}
puts("");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: