洛谷 P4171 [JSOI2010]满汉全席

一共有 \(K\) 场比赛,每场比赛有 \(n\) 种材料和 \(m\) 位评委。每种材料只能使用一次,可以用于制作该种材料对应的满式菜或汉式菜。每位评委都有喜爱的两种菜,只有选手做出这两种菜中的至少一种他才会满意。对每一场比赛判断是否有一种做菜方案使得所有评委满意。

2-SAT 裸题。

#include <cstdio>
#include <cstring>
#include <algorithm>

inline unsigned read(void){
	unsigned res = 0; char ch = std::getchar();
	while(ch < '0' || ch > '9')
		ch = std::getchar();
	while(ch >= '0' && ch <= '9')
		res = res * 10 + ch - 48, ch = std::getchar();
	return res;
}

const int MAXN = 1e2 + 19, MAXM = 1e3 + 19;

struct Edge{
	int to, next;
}edge[MAXM << 2];

int cnt, head[MAXN << 2];

inline void add(int from, int to){
	edge[++cnt].to = to;
	edge[cnt].next = head[from];
	head[from] = cnt;
}

int ind;
int dfn[MAXN << 2], low[MAXN << 2];
int stack[MAXN << 2], top, vist[MAXN << 2];
int color_cnt, color[MAXN << 2];

void dfs(int node){
	dfn[node] = low[node] = ++ind;
	stack[++top] = node; vist[node] = true;
	for(int i = head[node]; i; i = edge[i].next)
		if(!dfn[edge[i].to]){
			dfs(edge[i].to);
			low[node] = std::min(low[node], low[edge[i].to]);
		}
		else if(vist[edge[i].to])
			low[node] = std::min(low[node], low[edge[i].to]);
	if(dfn[node] == low[node]){
		++color_cnt;
		while(stack[top + 1] != node){
			color[stack[top]] = color_cnt;
			vist[stack[top]] = false;
			--top;
		}
	}
}

int n, m;
char meal1[9], meal2[9];
int mt1, mt2;
bool tp1, tp2;

void init(void){
	std::memset(head, 0, sizeof head);
	cnt = 0;
	ind = 0;
	std::memset(dfn, 0, sizeof dfn);
	std::memset(low, 0, sizeof low);
	std::memset(stack, 0, sizeof stack);
	top = 0;
	color_cnt = 0;
}

int main(){
	for(int T = read(); T; --T){
		init();
		n = read(), m = read();
		for(int i = 1; i <= m; ++i){
			std::scanf("%s%s", meal1, meal2);
			std::sscanf(meal1 + 1, "%d", &mt1);
			std::sscanf(meal2 + 1, "%d", &mt2);
			tp1 = meal1[0] == 'm';
			tp2 = meal2[0] == 'm';
			add(mt1 * 2 - tp1 + n * 2, mt2 * 2 - tp2);
			add(mt2 * 2 - tp2 + n * 2, mt1 * 2 - tp1);
		}
		for(int i = 1; i <= n; ++i){
			add(i * 2, i * 2 - 1 + n * 2);
			add(i * 2 - 1, i * 2 + n * 2);
		}
		for(int i = 1; i <= n * 4; ++i)
			if(!dfn[i])
				dfs(i);
		for(int i = 1; i <= n * 2; ++i)
			if(color[i] == color[i + n * 2]){
				std::puts("BAD");
				goto rep;
			}
		std::puts("GOOD");
		rep:;
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/natsuka/p/manhan_meal.html