POJ3683_Priest John's Busiest Day_2-sat
2018-01-18 13:39
375 查看
题意
n 对新人举行婚礼,每个婚礼需要神父参与一个特殊仪式,可以在婚礼的开始进行,也可以在婚礼的末尾举行。神父只有一位,他不能同时参与两场婚礼。给定每场婚礼的开始时间、结束时间、仪式时长,问是否有一种安排,使得神父可以不冲突地参加所有婚礼的特殊仪式。思路
对于每一场婚礼,只有两种选择:开始举行仪式,结尾举行仪式。这就可以用一个bool变量表示: x 取“真”表示在开始举行。由此可以把所有婚礼两两之间建立关系,并最终形成合取范式。例如:两场婚礼都选择开头(i 且 j) 时发生冲突,则有 非(i 且 j), 可转化为 (非i 或 非j), 进一步转化为 (i -> 非j) 且 (j -> 非i)。其冲突情形的处理方式类似。套用2-sat即可。
链接
http://poj.org/problem?id=3683代码
#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; const int maxn = 1000 + 10; const int maxv = maxn << 1; int n, v; int S[maxn], T[maxn], D[maxn]; vector<int> G[maxv], rG[maxv], vs; bool vis[maxv]; int cmp[maxv]; int read(){ int h, m; scanf("%d:%d", &h, &m); return h * 60 + m; } void add(int x, int y){ G[x].push_back(y); rG[y].push_back(x); } void dfs(int v){ vis[v] = true; for(int i = 0; i < G[v].size(); ++i){ if(!vis[G[v][i]]) dfs(G[v][i]); } vs.push_back(v); } void rdfs(int v, int k){ vis[v] = true; cmp[v] = k; for(int i = 0; i < rG[v].size(); ++i){ if(!vis[rG[v][i]]) rdfs(rG[v][i], k); } } int scc(){ memset(vis, false, sizeof vis); //第一遍dfs标序号(这里用有序数组代替) vs.clear(); for(int i = 0; i < n; ++i){ if(!vis[i]) dfs(i); } int k = 0; //第二遍反向dfs分连通分量 memset(vis, false, sizeof vis); for(int i = vs.size()-1; i >= 0; --i){ if(!vis[vs[i]]) rdfs(vs[i], k++); } return k; } bool solve(){ //处理冲突,建图 for(int i = 0; i < n; ++i){ for(int j = i+1; j < n; ++j){ if(min(S[i] + D[i], S[j] + D[j]) > max(S[i], S[j])){ add(i, j + n); add(j, i + n); } if(min(S[i] + D[i], T[j]) > max(S[i], T[j] - D[j])){ add(i, j); add(j + n, i + n); } if(min(T[i], S[j] + D[j]) > max(S[i] - D[i], S[j])){ add(i + n, j + n); add(j , i); } if(min(T[i], T[j]) > max(T[i] - D[i], T[j] - D[j])){ add(i + n, j); add(j + n, i); } } } scc(); //若 i 和 非i 在同一连通分量内,为矛盾式 for(int i = 0; i < n; ++i){ if(cmp[i] == cmp[i+n]){ return false; } } return true; } int main(){ scanf("%d", &n); for(int i = 0; i < n; ++i){ S[i] = read(); T[i] = read(); scanf("%d", D + i); } if(solve()){ puts("YES"); for(int i = 0; i < n; ++i){ if(cmp[i] > cmp[i+n]){ printf("%02d:%02d %02d:%02d\n", S[i] / 60, S[i] % 60, (S[i] + D[i]) / 60, (S[i] + D[i]) % 60); }else{ printf("%02d:%02d %02d:%02d\n", (T[i] - D[i]) / 60, (T[i] - D[i]) % 60, T[i] / 60, T[i] % 60); } } }else{ puts("NO"); } return 0; }
相关文章推荐
- POJ3683 Priest John's Busiest Day【2-SAT】
- POJ3683 Priest John's Busiest Day(神父约翰的忙日)题解(2-SAT及布尔方程运用)
- 【2-SAT任意解】POJ3683[Priest John's Busiest Day]题解
- 【POJ3683】Priest John's Busiest Day (2-sat输出任意解)
- 2-SAT——5.0(poj3683 Priest John's Busiest Day)
- poj3683 Priest John's Busiest Day【2-sat n+m算法】
- 2-SAT模板(scc强连通模板)-poj3683-Priest John's Busiest Day
- POJ 3683 Priest John's Busiest Day (2-SAT+输出可行解)
- 【POJ3683】Priest John's Busiest Day(Special Judge)
- POJ-3683 Priest John's Busiest Day(2-SAT问题)
- [2-sat]POJ 3683——Priest John's Busiest Day
- POJ 3683 - Priest John's Busiest Day(2-SAT)
- POJ 3683 Priest John's Busiest Day(2-sat)
- poj 3683 Priest John's Busiest Day 2_sat
- [2-SAT 任意解 Tarjan 模板题] POJ 3683 Priest John's Busiest Day
- |poj 3683|2-SAT|Priest John's Busiest Day
- POJ-3683-Priest John's Busiest Day(2-SAT染色)
- Poj3683:Priest John's Busiest Day
- POJ 3683 Priest John's Busiest Day 2-sat输出任意一组解
- poj3683 Priest John's Busiest Day