2-SAT练习 poj3683

Problem

Solution

既然要求时间不冲突,那么我们就O(n²)的去寻找冲突的时间对。若对于A这对夫妻与B这对夫妻,A[i]时间举行仪式和B[j]时间举行仪式的时间是冲突的(恰好无缝衔接不算冲突),那么就说明如果在A[i]时间举行仪式,一定就要在B[j^1]时间举行。若在B[j]时间举行,也一定要在A[i^1](这恰好是一个命题与他的逆否命题)。于是我们就可以按2-SAT的套路去解题了。

直接上代码:

#include <cstdio>
struct adj {int to, next;}e[4000010];
int n, S[1010], T[1010], D[1010], X[1010][2][2], head[2010], cnt = 1, dfn[2010], low[2010], num = 0, scc = 0, belong[2010], opp[2010], val[2010];
inline int mymin(int x, int y) {return x<y?x:y;}
inline void ins(int x, int y) {e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt;}
int sta[2010], top = 0; bool v[2010];
void tarjan(int x) {
	dfn[x] = low[x] = ++num;
	sta[++top] = x; v[x] = 1;
	for(int i = head[x]; i; i = e[i].next)
		if(!dfn[e[i].to]) {
			tarjan(e[i].to);
			low[x] = mymin(low[x], low[e[i].to]);
		}else if(v[e[i].to]) low[x] = mymin(low[x], dfn[e[i].to]);
	if(dfn[x] == low[x]) {
		++scc; int y;
		do {
			y = sta[top]; --top; v[y] = 0;
			belong[y] = scc;
		}while(x != y);
	}
}
inline void print(int i, int j) {printf("%.2d:%.2d %.2d:%.2d\n", X[i][j][0]/60, X[i][j][0] - X[i][j][0]/60 * 60, X[i][j][1]/60, X[i][j][1] - X[i][j][1]/60 * 60);}
int main() {
	scanf("%d", &n); char str1[10], str2[10];
	for(int i = 1; i <= n; ++i) {
		scanf("%s%s%d", str1, str2, &D[i]);
		S[i] = ((str1[0] - 48) * 10 + str1[1] - 48) * 60 + (str1[3] - 48) * 10 + str1[4] - 48;
		T[i] = ((str2[0] - 48) * 10 + str2[1] - 48) * 60 + (str2[3] - 48) * 10 + str2[4] - 48;
		X[i][0][0] = S[i]; X[i][0][1] = S[i] + D[i]; X[i][1][0] = T[i] - D[i]; X[i][1][1] = T[i];
	}
	for(int i = 1; i < n; ++i)
		for(int j = i + 1; j <= n; ++j)
			for(int p = 0; p <= 1; ++p)
				for(int q = 0; q <= 1; ++q)
					if(!(X[i][p][1] <= X[j][q][0] || X[i][p][0] >= X[j][q][1])) ins(i + p * n, j + (1 - q) * n), ins(j + q * n, i + (1 - p) * n);
			for(int i = 1; i <= 2 * n; ++i) if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= n; ++i) {
		if(belong[i] == belong[i + n]) {printf("NO"); return 0;}
		opp[i] = n + i; opp[i + n] = i;
	}
	printf("YES\n");
	for(int i = 1; i <= 2 * n; ++i) val[i] = belong[i] > belong[opp[i]];
	for(int i = 1; i <= n; ++i) print(i, val[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/richard_for_oi/article/details/79601726
今日推荐