UVA11294 Wedding

嘟嘟嘟

大佬们都说这是2-SAT入门题,然而对于刚学2_SAT的本菜鸡来说半天才理解……

题面:新娘和新郎不能坐在同一侧,妻子和丈夫不能坐在同一侧,有**关系的两个人必须至少一个坐在新娘一侧,问方案。

对于有**关系的两个人x, y,如果x坐在新郎一侧,那么y必须坐在新娘一侧,从而得出y的妻子(丈夫)必须坐在新郎一侧。那么令x表示妻子和新郎坐在同侧,x + n表示丈夫和新郎坐在同一侧。比如一对关系(3w, 5h)那么就连这么两条边:(3, 5)和((5 + n), (3 + n))。剩下同理。

有点坑儿的地方:

1.点从0开始。

2.别忘了新娘和新郎,所以连边(1, n + 1).

3.注意格式。

4.因为有spj,所以样例不过都可能AC。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 using namespace std;
 12 #define enter puts("")
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 1e3 + 5;
 21 const int maxm = 1e5 + 5;
 22 inline ll read()
 23 {
 24   ll ans = 0;
 25   char ch = getchar(), las = ' ';
 26   while(!isdigit(ch)) las = ch, ch = getchar();
 27   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
 28   if(las == '-') ans = -ans;
 29   return ans;
 30 }
 31 inline void write(ll x)
 32 {
 33   if(x < 0) putchar('-'), x = -x;
 34   if(x >= 10) write(x / 10);
 35   putchar(x % 10 + '0');
 36 }
 37 
 38 int n, m;
 39 struct Edge
 40 {
 41   int to, nxt;
 42 }e[maxm << 2];
 43 int head[maxn << 1], ecnt = 0;
 44 void addEdge(int x, int y)
 45 {
 46   e[++ecnt].to = y;
 47   e[ecnt].nxt = head[x];
 48   head[x] = ecnt;
 49 }
 50 
 51 stack<int> st;
 52 bool in[maxn << 1];
 53 int dfn[maxn << 1], low[maxn << 1], cnt = 0;
 54 int col[maxn << 1], ccol = 0;
 55 void tarjan(int now)
 56 {
 57   dfn[now] = low[now] = ++cnt;
 58   st.push(now); in[now] = 1;
 59   for(int i = head[now]; i; i = e[i].nxt)
 60     {
 61       if(!dfn[e[i].to])
 62     {
 63       tarjan(e[i].to);
 64       low[now] = min(low[now], low[e[i].to]);
 65     }
 66       else if(in[e[i].to]) low[now] = min(low[now], dfn[e[i].to]);
 67     }
 68   if(dfn[now] == low[now])
 69     {
 70       int x; ++ccol;
 71       do
 72     {
 73       x = st.top(); st.pop();
 74       col[x] = ccol; in[x] = 0;
 75     }while(x != now);
 76     }
 77 }
 78 
 79 int num(int x)
 80 {
 81   return x > n ? x - n : x + n;
 82 }
 83 
 84 void init()
 85 {
 86   while(!st.empty()) st.pop();
 87   for(int i = 1; i <= (n << 1); ++i)
 88     head[i] = dfn[i] = low[i] = col[i] = in[i] = 0;
 89   ecnt = cnt = ccol = 0;
 90 }
 91 
 92 int main()
 93 {
 94   while(scanf("%d%d", &n, &m), n > 0 || m > 0)
 95     {
 96       init();
 97       for(int i = 1; i <= m; ++i)
 98     {
 99       int x, y;
100       char c1, c2;
101       scanf("%d%c %d%c", &x, &c1, &y, &c2);
102       x++; y++;
103       if(c1 == 'h') x += n;
104       if(c2 == 'h') y += n;
105       addEdge(x, num(y));
106       addEdge(y, num(x));
107     }
108       addEdge(1, 1 + n);
109       for(int i = 1; i <= (n << 1); ++i) if(!dfn[i]) tarjan(i);
110       bool flg = 1;
111       for(int i = 1; i <= n && flg; ++i) if(col[i] == col[i + n]) flg = 0;
112       if(!flg) {puts("bad luck"); continue;}
113       for(int i = 2; i <= n; ++i) printf("%d%c%c", i - 1, col[i] > col[i + n] ? 'w' : 'h', " 
"[i == n]);
114       if(n < 2) enter;
115     }
116   return 0;
117 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9760480.html