描述
hihoCoder音乐节由hihoCoder赞助商大力主办,邀请了众多嘉宾和知名乐队参与演出。
音乐会分为上午、下午两场进行,主办方指定了n首歌让乐队进行演唱。每首歌只会被演唱一次,要么在上午要么在下午。
参加音乐会的嘉宾们对于歌曲的演唱时间有一些要求。具体来说,每位嘉宾会指定两首歌曲的演唱时间(上午或者下午)。如果最后实际的演出安排中,两首歌都没有达到嘉宾的要求,那么嘉宾就会对音乐节不滿意。如嘉宾A的要求是上午《我的滑板鞋》和下午《忐忑》,而最后的演出中上午没有《我的滑板鞋》只有《忐忑》,下午没有《忐忑》只有《我的滑板鞋》,那么嘉宾A是不满意的。
音乐节主办方自然希望使所有嘉宾满意,但主办方后来发现有可能不存在一种歌曲的安排方案满足所有嘉宾,所以他们希望你判断一下这种情况是否会发生。
输入
输入第一行包含一个数字 K,代表K组数据。(K≤50)
对于每一组数据,第一行包含两个非负整数n和m(n≤100,m≤1000),代表有n首歌和m位嘉宾。
为了方便我们给予歌编号,编号分别从1 到n。接下的m行,每行都代表对应的嘉宾的喜好由一个英文字母(m或h)跟一个数字代表,如m1 代表这个评审喜欢第1首歌上午进行,而h2代表这个评审员喜欢第2首歌下午进行。
输出
对于每一组数据,输出一行,如果能满足所有嘉宾的情况,输出GOOD;否则输出BAD。
样例输入
2
3 4
m3 h1
m1 m2
h1 h3
h3 m2
2 4
h1 m2
m2 m1
h1 h2
m1 h2
样例输出
GOOD
BAD
思路
2-SAT问题:一共有 N N N个选项 M M M个要求,求一种满足所有约束条件的方案
- 首先把 N N N个选项拆成 2 N 2N 2N个分别表示相反的状态
- 然后根据约束条件建图,例如 ( a (a (a or b ) b) b) 我们就建这样两个边: ¬ a ¬a ¬a–> b b b 和 ¬ b ¬b ¬b–> a a a 表示当 a a a不成立时 b b b一定要成立 或者 b b b不成立 a a a一定要成立,这样就能保证至少有一个条件满足,而且能能够尽可能的满足多个约束条件
- 矛盾情况就是,最后求得的一个联通分量里面包含有一个点的两个状态(这个状态既要满足又要不满足)就是矛盾
我把输入的数据按照字符串来处理刚开始一直WA,我在判断数字的时候只截取了S[1],编号可是100啊!
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#include <time.h>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
const int maxn = 305;
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
int tot, len, ts;
int low[maxn], dfn[maxn], Stack[maxn], inStack[maxn], belong[maxn];
vector<int> g[maxn];
void tarjan(int x) {
Stack[len++] = x;
inStack[x] = 1;
low[x] = dfn[x] = ++ts;
for (int i = 0; i < (int)g[x].size(); ++i) {
int y = g[x][i];
if (!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]);
else if (inStack[y]) low[x] = min(low[x], low[y]);
}
if (dfn[x] == low[x]) {
tot++;
int top;
do{
top = Stack[--len];
inStack[top] = 0;
belong[top] = tot;
}while (top != x);
}
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
map<char, int> mi;
mi['m'] = 0;
int T;
scanf("%d", &T);
int n, m;
while (T--) {
scanf("%d %d", &n, &m);
len = ts = tot = 0;
mem(inStack, 0);
mem(low, 0);
mem(Stack, 0);
mem(belong, 0);
mem(dfn, 0);
for (int i = 0; i < maxn; ++i) g[i].clear();
mi['h'] = n;
for (int i = 0; i < m; ++i) {
int l, r, l1, r1; // l,r 表示一个约束条件 l1,r1 分表表示反状态
char x, y;
scanf(" %c%d %c%d ", &x, &l, &y, &r);
l += mi[x];
r += mi[y];
l1 = l > n ? l-n : l+n;
r1 = r > n ? r-n : r+n;
// 建图
g[l1].push_back(r);
g[r1].push_back(l);
}
// tarjan
for (int i = 1; i<= n*2; ++i) {
if (!dfn[i]) tarjan(i);
}
int flag = 0;
for (int i = 1; i <= n; ++i) {
if (belong[i] == belong[i+n]) flag = 1;
}
puts(flag ? "BAD" : "GOOD");
}
return 0;
}