英文太差了, 这个题目愣是半天没看懂 , 后面看别人翻译才看懂 , 英语是硬伤啊
题目大意:给 n 对夫妇安排座位 , 0h , 0w表示新郎新娘 , 新娘只能看到坐在她对面那一排的人 , 要求:
1、同一对新郎新娘不能做在同一侧
2、有m对人互为通奸(可以男男、女女、男女) , 新娘不能同时看到互为通奸的两个人。
注意:新郎也有可能和其他人通奸
做法:
1、分两种情况讨论 , 新娘在左侧 ,
新娘在右侧 , 分别建图进行 2-SAT算法
2、不分左侧还是右侧 , 只分和新娘同侧或不同侧
下面给出做法一的代码
#include <iostream> #include <vector> #include <stdio.h> #include <string.h> using namespace std; #define maxn 200000 int n , m; int a[maxn][2]; vector<int>grap[maxn]; bool mark[maxn]; int s[maxn]; int c; void init() { memset(mark , 0 , sizeof(mark)); for(int i = 0; i < 4*n; i++) grap[i].clear(); } void add_edge(int x , int y) { grap[x].push_back(y); //cout<<x<<",,"<<y<<endl; } bool dfs(int u) { if(mark[u^1]) return false; if(mark[u]) return true; mark[u] = true; s[c++] = u; for(int i = 0; i < grap[u].size(); i++) { if(!dfs(grap[u][i])) return false; } return true; } bool slove() { int i; for(i = 0; i < n*4; i += 2) { if(!mark[i] && !mark[i+1]) { c = 0; if(!dfs(i)) { while(c > 0) mark[s[--c]] = false; if(!dfs(i+1)) return false; } } } return true; } void print(int i) { int bz = true; for( ; i < 4*n ; i += 2) { if(i == 2*n || i == 2*n+1) continue; if(mark[i]) { if(i >= 2*n) { if(bz) printf("%dh" , (i-2*n)/2) , bz = false; else printf("% dh" , (i-2*n)/2); } else { if(bz) printf("%dw" , i/2) , bz = false; else printf("% dw" , i/2); } } } cout<<endl; } int main() { while(scanf("%d %d" , &n , &m) != EOF) { if(n == 0 && m == 0) break; //n -= 1; init(); int i ; int x , y; char px , py; for(i = 0; i < m; i++) { scanf("%d%c %d%c" , &x , &px , &y , &py); //x -= 1; y -= 1; if(px == ‘h‘) a[i][0] = 2*n+x*2; else a[i][0] = x*2; if(py == ‘h‘) a[i][1] = 2*n+y*2; else a[i][1] = y*2; } for(i = 2; i < 2*n; i += 2) //夫妻之间 { add_edge(i , 2*n+i+1); add_edge(2*n+i+1,i ); add_edge(i+1 , 2*n+i); add_edge(2*n+i , i+1); } for(i = 0; i < m; i++) //仇人之间 { add_edge(a[i][0]+1 , a[i][1]); add_edge(a[i][1]+1 , a[i][0]); } mark[0] = mark[2*n+1] = true; bool bz = slove(); if(!bz) { init(); for(i = 0; i < 2*n; i += 2) //夫妻之间 { add_edge(i , 2*n+i+1); add_edge(2*n+i+1 ,i ); add_edge(i+1 , 2*n+i); add_edge(2*n+i , i+1); } for(i = 0; i < m; i++) //仇人之间 { add_edge(a[i][0] , a[i][1]+1); add_edge(a[i][1] , a[i][0]+1); } mark[1] = mark[2*n] = true; bz = slove(); if(!bz) printf("bad luck\n"); else { print(3); } } else { print(2); } } return 0; }
uva 11294 2-SAT问题,码迷,mamicode.com
时间: 2024-10-12 06:33:05