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

【题解】:比较明显的2-sat,我们可以把问题转化为求坐在新娘对面的人的可行方案。
              对于m对有通奸关系的x 和 y,连边x->y', y->x'.
              最后新娘向新郎连一条边,表示新郎一定要坐在新娘的对面,然后就是解2-sat的基本步骤了,输出方案时利用染色把与新娘同色的人输出。

【代码】:
  1 #include "iostream"
  2 #include "cstring"
  3 #include "cstdio"
  4 #include "vector"
  5 using namespace std;
  6 #define maxn 5010
  7 vector<int> vec[maxn], rvec[maxn], dag[maxn];
  8 int belong[maxn], scc, top, s[maxn], color[maxn];
  9 int n, m;
 10 bool visit[maxn];
 11 void init() {
 12     for(int i = 0; i < maxn; i++) vec[i].clear(), rvec[i].clear(), dag[i].clear();
 13 }
 14 int cal(int a, char ch) {
 15     int res = a * 2;
 16     if(ch == 'h'return res;
 17     else return res + 1;
 18 }
 19 void dfs1(int u) {
 20     visit[u] = true;
 21     int size = vec[u].size();
 22     for(int i = 0; i < size; i++) {
 23         int v = vec[u][i];
 24         if(!visit[v]) dfs1(v);
 25     }
 26     s[++top] = u;
 27 }
 28 void dfs2(int u) {
 29     visit[u] = true;
 30     int size = rvec[u].size();
 31     for(int i = 0; i < size; i++) {
 32         int v = rvec[u][i];
 33         if(!visit[v]) dfs2(v);
 34     }
 35     belong[u] = scc;
 36 }
 37 void kosaraju() {
 38     scc = top = 0;
 39     memset(visit, falsesizeof(visit));
 40     for(int i = 0; i < 2 * n; i++
 41         if(!visit[i]) dfs1(i);
 42     memset(visit, falsesizeof(visit));
 43     for(int i = 2 * n; i; i--
 44         if(!visit[s[i]]) scc++, dfs2(s[i]);
 45     for(int u = 0; u < 2 * n; u++) {
 46         int size = rvec[u].size();
 47         for(int i = 0; i < size; i++) {
 48             int v = rvec[u][i];
 49             if(belong[u] != belong[v]) dag[belong[u]].push_back(belong[v]);
 50         }
 51     }
 52 }
 53 bool solvable() {
 54     for(int i = 0; i < 2 * n; i += 2)
 55         if(belong[i] == belong[i+1]) return false;
 56     return true;
 57 }
 58 void dfs(int u) {
 59     color[u] = 2;
 60     int size = dag[u].size();
 61     for(int i = 0; i < size; i++) {
 62         int v = dag[u][i];
 63         if(!color[v]) dfs(v);
 64     }
 65 }
 66 void solve() {
 67     memset(color, 0sizeof(color));
 68     for(int i = scc; i; i--) {
 69         if(!color[i]) {
 70             color[i] = 1;
 71             for(int j = 0; j < 2 * n; j++) {
 72                 if(belong[j] == i) {
 73                     int k = belong[j^1];
 74                     if(!color[k]) dfs(k);
 75                 }
 76             }
 77         }
 78     }
 79     for(int i = 2; i < 2 * n; i++)
 80         if(color[belong[i]] == color[belong[1]])
 81             printf("%d%c ", i / 2, i & 1 ? 'w' : 'h');
 82     printf("\n");
 83 }
 84 void debug() {
 85     for(int i = 0; i < 2 * n; i++) {
 86         int size = vec[i].size();
 87         for(int j = 0; j < size; j++) {
 88             cout << i << "->" << vec[i][j] << endl;
 89         }
 90     }
 91     cout << endl;
 92     for(int i = 1; i <= scc; i++) {
 93         int size = dag[i].size();
 94         for(int j = 0; j < size; j++) {
 95             cout << i << "->" << dag[i][j] << endl;
 96         }
 97     }
 98 }
 99 int main() {
100     char ch1, ch2;
101     int a, b;
102     while(~scanf("%d%d"&n, &m)) {
103         getchar();
104         if(!&& !m) break;
105         init();
106         for(int i = 0; i < m; i++) {
107             scanf("%d%c%d%c"&a, &ch1, &b, &ch2);
108             getchar();
109             int u = cal(a, ch1), v = cal(b, ch2);
110             vec[u].push_back(v^1), vec[v].push_back(u^1);
111             rvec[v^1].push_back(u), rvec[u^1].push_back(v);
112         }
113         vec[1].push_back(0), rvec[0].push_back(1);
114         kosaraju();
115         if(solvable()) solve();
116         else printf("bad luck\n");
117     }
118     return 0;
119 }