1. 程式人生 > >POJ 3683 Priest John's Busiest Day(2-sat)

POJ 3683 Priest John's Busiest Day(2-sat)

ant log ret ims esp top gin csdn can

POJ 3683 Priest John‘s Busiest Day

id=3683">題目鏈接

題意:給定幾個時間,si, ti, di每一個時間要選[si, si + di]或[ti - di, ti],問是否能選出全部時間不相交的方案

思路:顯然的2-sat,註意推斷相交的方法

代碼:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int N = 1005;


int n;
vector<int> g[2 * N];
bool mark[2 * N];

void init() {
	memset(mark, false, sizeof(mark));
	for (int i = 0; i < 2 * n; i++) g[i].clear();
}

void add_edge(int u, int x, int v, int y) {
	g[(2 * u + x)^1].push_back(2 * v + y);
	g[(2 * v + y)^1].push_back(2 * u + x);
}

int s[N], e[N], d[N];

int S[2 * N], sn;

bool dfs(int u) {
	if (mark[u^1]) return false;
	if (mark[u]) return true;
	mark[u] = true;
	S[sn++] = u;
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i];
		if (!dfs(v)) return false;
	}
	return true;
}

bool judge(int s1, int e1, int s2, int e2) {
	if (s1 >= s2 && s1 < e2) return true;
	if (s2 >= s1 && s2 < e1) return true;
	return false;
}

bool solve() {
	init();
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < i; j++) {
			for (int x = 0; x < 2; x++) {
				for (int y = 0; y < 2; y++) {
					int s1, e1, s2, e2;
					if (x == 0) {
						s1 = s[i];
						e1 = s[i] + d[i];
					} else {
						s1 = e[i] - d[i];
						e1 = e[i];
					}
					if (y == 0) {
						s2 = s[j];
						e2 = s[j] + d[j];
					} else {
						s2 = e[j] - d[j];
						e2 = e[j];
					}
					if (s1 > e1 || s2 > e2) return false;
					if (judge(s1, e1, s2, e2))
						add_edge(i, !x, j, !y);
				}
			}
		}
	}
	for (int i = 0; i < n * 2; i += 2) {
		if (!mark[i] && !mark[i + 1]) {
			sn = 0;
			if (!dfs(i + 1)) {
				for (int j = 0; j < sn; j++) mark[S[j]] = false;
				sn = 0;
				if (!dfs(i)) return false;
			}
		}
	}
	return true;
}

int main() {
	while (~scanf("%d", &n)) {
		int h1, m1, h2, m2;
		for (int i = 0; i < n; i++) {
			scanf("%d:%d%d:%d%d", &h1, &m1, &h2, &m2, &d[i]);
			s[i] = h1 * 60 + m1; e[i] = h2 * 60 + m2;
		}
		if (!solve()) printf("NO\n");
		else {
			printf("YES\n");
			for (int i = 0; i < n; i++) {
				int st, et;
				if (mark[i * 2]) {
					st = s[i];
					et = s[i] + d[i];
				} else {
					st = e[i] - d[i];
					et = e[i];
				}
				printf("%02d:%02d %02d:%02d\n", st / 60, st % 60, et / 60, et % 60);
			}
		}
	}
	return 0;
}


POJ 3683 Priest John's Busiest Day(2-sat)