题目大意:
给出
N对夫妻
N
对
夫
妻
,从
第0对开始
第
0
对
开
始
,现在有一场宴会,可以坐两排,
wife0
w
i
f
e
0
必须做左边,
husband0必须坐右边
h
u
s
b
a
n
d
0
必
须
坐
右
边
,其他的夫妻不能坐在同一边,给出
M
M
对通奸关系,有通奸关系的不能同时出现在的对面。
问是否存在一种可行安排方案,存在则输出可行方案的任意解。
分析:
这题真的坑啊..
题目可以转化成一道2-SAT模型,
我们设
i表示wifei坐在左边
i
表
示
w
i
f
e
i
坐
在
左
边
i+n表示hubandi坐在左边
i
+
n
表
示
h
u
b
a
n
d
i
坐
在
左
边
i+2∗n表示wifei坐在右边
i
+
2
∗
n
表
示
w
i
f
e
i
坐
在
右
边
i+n+2∗n表示hubandi坐在右边
i
+
n
+
2
∗
n
表
示
h
u
b
a
n
d
i
坐
在
右
边
显然
wife0
w
i
f
e
0
必须要坐在左边,
husband0
h
u
s
b
a
n
d
0
必须坐在右边,
所以连边
2∗n−>0
2
∗
n
−
>
0
,
n−>3∗n
n
−
>
3
∗
n
保证
然后将所有的夫妻
wifei,husbandi
w
i
f
e
i
,
h
u
s
b
a
n
d
i
(
i≠0
i
≠
0
)连边
i−>i+n+2∗n
i
−
>
i
+
n
+
2
∗
n
,
i+n+2∗n−>i
i
+
n
+
2
∗
n
−
>
i
i+2∗n−>i+n
i
+
2
∗
n
−
>
i
+
n
,
i+n−>i+2∗n
i
+
n
−
>
i
+
2
∗
n
注意同时坐在
wife0
w
i
f
e
0
一边(左边)乱搞是允许的有点怪异
所以当其中一个坐右边时另一个必须坐右边,而一个坐左边时另一个怎么选都可以。
当
wifei跟wifej
w
i
f
e
i
跟
w
i
f
e
j
乱搞
连边
i+2∗n−>j
i
+
2
∗
n
−
>
j
,
j+2∗n−>i
j
+
2
∗
n
−
>
i
当
wifei跟husbandj
w
i
f
e
i
跟
h
u
s
b
a
n
d
j
乱搞
连边
i+2∗n−>j+n
i
+
2
∗
n
−
>
j
+
n
,
j+n+2∗n−>i
j
+
n
+
2
∗
n
−
>
i
当
husbandi跟husbandj
h
u
s
b
a
n
d
i
跟
h
u
s
b
a
n
d
j
乱搞
连边
i+n+2∗n−>j+n
i
+
n
+
2
∗
n
−
>
j
+
n
,
j+n+2∗n−>i+n
j
+
n
+
2
∗
n
−
>
i
+
n
然后强连通分量判有无解,
缩点拓扑找方案即可
因为有多组数据,所以每次数组都要注意清零,
可是偏偏我用了个叫做vector的东东,
然后vector我只是clear了..而size并没有清零,所以拓扑的部分凉了..
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#define M 2000005
#define N 2005
using namespace std;
stack <int> st;
queue <int> Q;
struct Node {
int u, v, next;
} a[M];
int Instack[N], Belong[N], dfn[N], low[N], Ls[N], cnt, tot, num, n, m;
int Cp[N], Rd[N], Color[N];
void Addedge(int u, int v) {
cnt++;
a[cnt].u = u;
a[cnt].v = v;
a[cnt].next = Ls[u];
Ls[u] = cnt;
}
void Clear_init() {
for (int i = 0 ; i < 4 * n; i++)
Ls[i] = Rd[i] = dfn[i] = low[i] = Color[i] = Instack[i] = 0;
tot = num = cnt = 0;
}
void Tarjan(int u) {
dfn[u] = low[u] = ++num;
Instack[u] = 1;
st.push(u);
for (int i = Ls[u]; i; i = a[i].next) {
int v = a[i].v;
if (!dfn[v]){
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (Instack[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
tot++;
int rp;
while ("rp++") {
rp = st.top();
st.pop();
Instack[rp] = 0;
Belong[rp] = tot;
if (rp == u) break;
}
}
}
void Top_sort() {
vector <int> E[N];
for (int i = 1; i <= cnt; i++) {
int u =a[i].u, v = a[i].v;
if (Belong[u] != Belong[v]) {
E[Belong[v]].push_back(Belong[u]);
Rd[Belong[u]]++;
}
}
for (int i = 1; i <= tot; i++)
if (!Rd[i]) Q.push(i);
while (!Q.empty()) {
int u = Q.front();
Q.pop();
if (!Color[u]) {
Color[u] = 1;
Color[Cp[u]] = 2;
}
for (int i = 0; i < E[u].size(); i++){
Rd[E[u][i]]--;
if (!Rd[E[u][i]]) Q.push(E[u][i]);
}
}
}
bool solve_problem() {
for (int i = 0; i < 4 * n; i++)
if (!dfn[i]) Tarjan(i);
for (int i = 0; i < 2 * n; i++) {
if (Belong[i] == Belong[i + 2 * n]) return 0;
Cp[Belong[i]] = Belong[i + 2 * n];
Cp[Belong[i + 2 * n]] = Belong[i];
}
Top_sort();
return 1;
}
int main() {
while (~scanf("%d %d", &n, &m)) {
if (!n && !m) break;
Clear_init();
Addedge(2 * n, 0);
Addedge(n, 3 * n);
for (int i = 1; i < n; i++) {
Addedge(i, i + n + 2 * n);
Addedge(i + n + 2 * n, i);
Addedge(i + 2 * n, i + n);
Addedge(i + n, i + 2 * n);
}
int x, y;
char aa, bb;
for (int i = 1; i <= m; i++) {
scanf("%d%c %d%c", &x, &aa, &y, &bb);
if (aa == 'h') x = x + n;
if (bb == 'h') y = y + n;
Addedge(x + 2 * n, y);
Addedge(y + 2 * n, x);
}
int count = 0;
if (solve_problem()) {
for (int i = 1; i < n; i++) {
if (Color[Belong[i]] == 1) {
printf("%dw", i);
count++;
if (count != (n - 1)) printf(" ");
else printf("\n");
} else {
printf("%dh", i);
count++;
if (count != (n - 1)) printf(" ");
else printf("\n");
}
}
} else printf("bad luck\n");
}
return 0;
}