poj3648 2-sat 输出任意一组解
生活随笔
收集整理的這篇文章主要介紹了
poj3648 2-sat 输出任意一组解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:
? ? ? 一對夫妻結(jié)婚,請來了n對夫妻,所有人坐在同一張桌子上吃飯,這張桌子是長方形的可以坐兩排人,有如下限制
(1) 新娘和新郎不做同一側(cè)。
(2) 每對來的夫妻也不能坐在同一側(cè)。?
(3) 有一些人有曖昧關(guān)系(男女,男男,或者女女),有曖昧關(guān)系的兩
思路:
? ? ? 一對夫妻結(jié)婚,請來了n對夫妻,所有人坐在同一張桌子上吃飯,這張桌子是長方形的可以坐兩排人,有如下限制
(1) 新娘和新郎不做同一側(cè)。
(2) 每對來的夫妻也不能坐在同一側(cè)。?
(3) 有一些人有曖昧關(guān)系(男女,男男,或者女女),有曖昧關(guān)系的兩
個人不可以同時坐在新娘對面。
思路:
? ? ?根據(jù)限制關(guān)系,而且還是二選一,顯然這個是2sat,對于每個人,都拆成兩個點,一個是a表示坐在新娘這一側(cè),另一個是~a表示坐在新郎這一側(cè),則對于任何有曖昧關(guān)系的,要么一邊坐一個,要不同時坐在新娘這一側(cè),則只要他們兩個中至少有一個1就行了,建圖是這樣 ~a -> b ,~b?-> a,對于每一對,他們不能坐在同一側(cè)則不能相同,建圖是 a -> ~b ,b?-> ~a ,~a ->b ,~b -> a ,還有就是新娘必須坐在新娘這側(cè),直接 ~a?-> a.
#include<stdio.h> #include<string.h> #include<stack>#define N_node 5000 #define N_edge 100000 #define R 1 #define B 2using namespace std;typedef struct {int to ,next; }STAR;STAR E1[N_edge] ,E2[N_edge]; int list1[N_node] ,list2[N_node] ,tot; int Belong[N_node] ,cnt; int mark[N_node] ,Col[N_node]; stack<int>st ,stt;void add(int a ,int b) {E1[++tot].to = b;E1[tot].next = list1[a];list1[a] = tot;E2[tot].to = a;E2[tot].next = list2[b];list2[b] = tot; }void DFS1(int s) {mark[s] = 1;for(int k = list1[s] ;k ;k = E1[k].next)if(!mark[E1[k].to]) DFS1(E1[k].to);st.push(s) ,stt.push(s); }void DFS2(int s) {mark[s] = 1;Belong[s] = cnt;for(int k = list2[s] ;k ;k = E2[k].next)if(!mark[E2[k].to]) DFS2(E2[k].to); }bool solve(int n) {memset(mark ,0 ,sizeof(mark));while(!st.empty()) st.pop();while(!stt.empty()) stt.pop();for(int i = 0 ;i < 4 * n ;i ++)if(!mark[i]) DFS1(i);memset(mark ,0 ,sizeof(mark)) ,cnt = 0;while(!st.empty()){int xin = st.top();st.pop();if(mark[xin]) continue;cnt ++;DFS2(xin);}for(int i = 0 ;i < n * 4 ;i += 2)if(Belong[i] == Belong[i^1]) return 0;return 1; }int main () {int i ,n ,m ,a ,b;char c1 ,c2;while(~scanf("%d %d" ,&n ,&m) && n + m){memset(list1 ,0 ,sizeof(list1));memset(list2 ,0 ,sizeof(list2)) ,tot = 1;for(i = 1 ;i <= m ;i ++){scanf("%d%c%d%c" ,&a ,&c1 ,&b ,&c2);a = a * 2 + (c1 == 'h' ? 1 : 0);b = b * 2 + (c2 == 'h' ? 1 : 0);add(a * 2 + 1 ,b * 2);add(b * 2 + 1 ,a * 2);} for(i = 0 ;i < n ;i ++){a = i * 2 ,b = i * 2 + 1;add(a * 2 + 1 ,b * 2) ,add(b * 2 + 1 ,a * 2);add(a * 2 ,b * 2 + 1) ,add(b * 2 ,a * 2 + 1);}add(1 ,0);if(!solve(n)){printf("bad luck\n");continue;}memset(Col ,0 ,sizeof(Col));while(!stt.empty()){i = stt.top() ,stt.pop();if(Col[i]) continue;Col[i] = B ,Col[i^1] = R;}int mk = 0;for(i = 4 ;i < n * 4 ;i += 2){ if(Col[i] == B) continue;if(mk) printf(" ");mk = 1;printf("%d" ,i / 4);i % 4 > 1 ? printf("h") : printf("w");}puts("");}return 0; }
總結(jié)
以上是生活随笔為你收集整理的poj3648 2-sat 输出任意一组解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1814 字典序最小的2sat(
- 下一篇: hdu4421 2-sat(枚举二进制每