hihoCoder 1467 2-SAT·hihoCoder音乐节(2-SAT模版)
#1467 : 2-SAT·hihoCoder音乐节
描述
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
题目链接:hihoCoder 1467
给定N个表演,M个要求,每一个限制有两个条件,至少成立一个条件这个限制就算满足,求是否存在这种安排。
比较模版的一题,显然每一个节目存在矛盾的两个面:要么早上表演,要么晚上表演,因此把一个节目拆成两个点,$i(=i)$代表早上表演,$\lnot i(=n+i)$代表晚上表演,那么对于任意一个形如 $a\lor b$的限制,添加 $\lnot a\to b$与$\lnot b\to a$两条有向边,然后用Tarjan求强连通分量,然后遍历每一个节目拆出来的两个点,若发现存在一个节目的$i$与$\lnot i$在同一连通分量中,说明这两个处于同样的状态,但事实上不可能共存,因此可以判断为BAD,否则为GOOD
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); typedef pair< int , int > pii; typedef long long LL; const double PI = acos (-1.0); const int N = 210; const int M = 1010; struct edge { int to, nxt; edge() {} edge( int _to, int _nxt): to(_to), nxt(_nxt) {} }; edge E[M << 1]; int head[N], tot; int dfn[N], low[N], st[N], ts, top, belong[N], scc; bitset<N>ins; void init() { CLR(head, -1); tot = 0; CLR(dfn, 0); CLR(low, 0); ts = top = scc = 0; CLR(belong, 0); ins.reset(); } inline void add( int s, int t) { E[tot] = edge(t, head[s]); head[s] = tot++; } void Tarjan( int u) { dfn[u] = low[u] = ++ts; ins[u] = 1; st[top++] = u; int i, v; for (i = head[u]; ~i; i = E[i].nxt) { v = E[i].to; if (!dfn[v]) { Tarjan(v); low[u] = min(low[u], low[v]); } else if (ins[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { ++scc; do { v = st[--top]; ins[v] = 0; belong[v] = scc; } while (u != v); } } int main( void ) { int T, n, m, a, b, i; char q, p; scanf ( "%d" , &T); while (T--) { init(); scanf ( "%d%d" , &n, &m); for (i = 0; i < m; ++i) { scanf ( " %c%d %c%d" , &q, &a, &p, &b); if (q == 'm' && p == 'm' ) { add(a + n, b); add(b + n, a); } else if (q == 'm' && p == 'h' ) { add(a + n, b + n); add(b, a); } else if (q == 'h' && p == 'm' ) { add(a, b); add(b + n, a + n); } else { add(a, b + n); add(b, a + n); } } int sz = n << 1; for (i = 1; i <= sz; ++i) if (!dfn[i]) Tarjan(i); bool flag = true ; for (i = 1; i <= n && flag; ++i) if (belong[i] == belong[i + n]) flag = false ; puts (flag ? "GOOD" : "BAD" ); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步