poj3683
poj3683
题意
n对新人举行婚礼,婚礼在不同时间段但可能重叠,婚礼有开始(Si)、结束(Ti)、仪式举行时间(Di),问能否给出一种举行方案,使得神父能参加所有的婚礼并举行仪式。
分析
xi为真 <=> 在开始时举行仪式,
xj为假 <=> 在结束时举行仪式。
设x' 为 非x。(若 x 为真,则 x' 为假)
xi -> xj 表示 xi 为真则 xj 为真。(xi xj 连边)
对于结婚仪式 i 和 j ,如果 Si ~ Si+Di 和 Sj ~ Sj+Dj 冲突,就有 xi' or xj' ,这种情况即 xi -> xj' ,xj -> xi' 。(xi 和 xj 不能同时选,即选择一个,那么选了 xi 后 就会选择到 xj' ,表示不选 xj。)
如果 Si ~ Si+Di 和 Tj-Dj ~ Dj 冲突,有 xi' or xj ,即 xi -> xj,xj' -> xi' 。
如果 Ti-Di ~ Ti 和 Sj ~ Sj+Dj 冲突,有 xi or xj' ,即 xi' -> xj',xj -> xi 。
如果 Ti-Di ~ Ti 和 Tj-Dj ~ Dj 冲突 ,有 xi or xj ,即 xi' -> xj ,xj' -> xi 。
代码参照《 挑战程序设计竞赛》,网上的代码大多是按照论文进行模拟?
书中有个步骤比较疑惑,打印可行解时,
x 所在的强连通分量的拓扑序在 x' 所在的强连通分量之后 <=> x 为真。
一点理解:拓扑序靠后的出度小,越不会影响后面的选择?
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
typedef long long ll;
using namespace std;
const int MAXN = 2e3 + 10;
int n, m; // 点、边
int vis[MAXN];
int flag[MAXN]; // 所属强连通分量的拓扑序
vector<int> G[MAXN], rG[MAXN];
vector<int> vs; // 后序遍历顺序的顶点列表
void addedge(int x, int y)
{
G[x].push_back(y); // 正向图
rG[y].push_back(x); // 反向图
}
void dfs(int u)
{
vis[u] = 1;
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i];
if(!vis[v]) dfs(v);
}
vs.push_back(u);
}
void rdfs(int u, int k)
{
vis[u] = 1;
flag[u] = k;
for(int i = 0; i < rG[u].size(); i++)
{
int v = rG[u][i];
if(!vis[v]) rdfs(v, k);
}
}
int scc() // 强连通分量的个数
{
vs.clear();
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) // [1...n]
if(!vis[i]) dfs(i);
memset(vis, 0, sizeof vis);
int k = 0;
for(int i = vs.size() - 1; i >= 0; i--)
if(!vis[vs[i]]) rdfs(vs[i], k++);
return k;
}
int S[MAXN], D[MAXN], T[MAXN];
void solve()
{
int N = n;
n = 2 * n;
for(int i = 1; i <= n; i++)
{
G[i].clear();
rG[i].clear();
}
for(int i = 1; i <= n; i++) // 枚举、连边
{
for(int j = 1; j < i; j++)
{
if(min(S[i] + D[i], S[j] + D[j]) > max(S[i], S[j]))
{
// xi -> xj' ,xj -> xi'
addedge(i, j + N);
addedge(j, i + N);
}
if(min(S[i] + D[i], T[j]) > max(S[i], T[j] - D[j]))
{
// xi -> xj,xj' -> xi'
addedge(i, j);
addedge(j + N, i + N);
}
if(min(T[i], S[j] + D[j]) > max(S[j], T[i] - D[i]))
{
// xi' -> xj',xj -> xi
addedge(i + N, j + N);
addedge(j, i);
}
if(min(T[i], T[j]) > max(T[i] - D[i], T[j] - D[j]))
{
// xi' -> xj ,xj' -> xi
addedge(i + N, j);
addedge(j + N, i);
}
}
}
scc();
// 判断可行性
for(int i = 1; i <= N; i++)
{
if(flag[i] == flag[N + i])
{
puts("NO");
return;
}
}
// 输出可行解
puts("YES");
for(int i = 1; i <= N; i++)
{
if(flag[i] > flag[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);
}
}
int main()
{
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
{
int x1, y1, x2, y2;
char p, q;
scanf("%02d:%02d %02d:%02d %d", &x1, &y1, &x2, &y2, &D[i]);
S[i] = x1 * 60 + y1;
T[i] = x2 * 60 + y2;
}
solve();
}
return 0;
}
poj3683的更多相关文章
- 2-sat——输出方案poj3683
一篇讲的详细的博客 https://blog.csdn.net/Hawo11/article/details/74908233 缩点后为什么要建立反图? 如果是按原图处理,选择一个点之后要把所有其后续 ...
- 2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683
Priest John's Busiest Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8170 Accept ...
- poj3683 Priest John's Busiest Day
2-SAT 输出可行解 找可行解的方案就是: 根据第一次建的图建一个反图..然后求逆拓扑排序,建反图的原因是保持冲突的两个事件肯定会被染成不同的颜色 求逆拓扑排序的原因也是为了对图染的色不会发生冲突, ...
- poj3683 Priest John's Busiest Day
2-SAT. 读入用了黄学长的快速读入,在此膜拜感谢. 把每对时间当作俩个点.如果有交叉代表相互矛盾. 然后tarjan缩点,这样就能得出当前的2-SAT问题是否有解. 如果有解,跑拓扑排序就能找出一 ...
- POJ3683 Falsita
http://poj.org/problem?id=3683 思路:2-SAT,输出任意一组方案,O(m+n) #include<cstdio> #include<iostream& ...
- 【POJ3683】Priest John's Busiest Day
题目 John is the only priest in his town. September 1st is the John's busiest day in a year because th ...
- Poj3683:Priest John's Busiest Day
题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然 ...
- POJ3683 Priest John's Busiest Day(2-SAT)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11049 Accepted: 3767 Special Judge ...
- poj3683(2-SAT 求任意方案)
基础的2-SAT求任意方案的题目. Priest John's Busiest Day Time Limit: 2000MS Memory Limit: 65536K Total Submissi ...
随机推荐
- spring之bean
Bean的基本配置 id属性 id属性确定bean的唯一标识符,容器对bean的管理,访问,以及该bean的依赖关系,都通过该属性来完成.bean的id属性在Spring容器中应该是唯一的. clas ...
- [JavaWeb]SpringSecurity-OAuth2.0 统一认证、资源分离的配置,用于分布式架构、模块化开发的认证体系
前言 关于 OAuth2.0的认证体系,翻阅了好多资料,RCF 文档太多,看了一半就看不下去了,毕竟全英文的文档看起来,是有一点让我烦躁,但也对 OAuth2.0的认证流程有了一个基本的概念,之前用 ...
- Entity Framework查询注意
首先我们看下where的方法,直接查看定义(定义如下),其实一种是对IEnumerable的扩展,一种是对IQueryable的扩展,直接看最常用的,其实区别就在IEnumerable的扩展的参数是系 ...
- SAP RFC函数远程调试跟踪管理软件
最近在搞OA系统与sap的接口开发,接口太多老是和.net的开发人员打嘴仗,为了避免不必要的纠结,自己做了一个rfc的调试工具,有些问题调试起来也比较容易了.程序是delphi开发的,为了保证程序可以 ...
- C#如何向word文档插入一个新段落及隐藏段落
编辑Word文档时,我们有时会突然想增加一段新内容:而将word文档给他人浏览时,有些信息我们是不想让他人看到的.那么如何运用C#编程的方式巧妙地插入或隐藏段落呢?本文将与大家分享一种向Word文档插 ...
- Python 基础 一
Python 基础 一 一.关于Python的介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum),这一两年在国内很流行,应用很广泛. 二.Python的基础知识(1) 1 ...
- lxml简明教程
最近要做下微信爬虫,之前写个小东西都是直接用正则提取数据就算了,如果需要更稳定的提取数据,还是使用 xpath 定位元素比较可靠.周末没事,从爬虫的角度研究了一下 python xml 相关的库. P ...
- sql关键字之null
在数据库中使用一种特殊的值表示未知的值--NULL,我们称之为空值但并不是空的字符串,而是特殊的值.
- Hush Framework框架配置
在写这篇文章的时候,楼主已经饿的不行了,因为我从3点开始就在折腾Hush Framework,走了很多弯路,打铁要趁热,先把基本的过程记录下来,留待以后翻阅,同时记录其中容易走弯路的地方,特别是对于一 ...
- Git下载、更新、提交使用总结
Git使用总结 1.下载代码到本地 1.1指定存储文件路径 1.运行git-bash.exe 2.指定盘符:cd f:work 1.2下载代码 命令:$ git clone <版本库的网址> ...