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的更多相关文章

  1. 2-sat——输出方案poj3683

    一篇讲的详细的博客 https://blog.csdn.net/Hawo11/article/details/74908233 缩点后为什么要建立反图? 如果是按原图处理,选择一个点之后要把所有其后续 ...

  2. 2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683

    Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8170   Accept ...

  3. poj3683 Priest John's Busiest Day

    2-SAT 输出可行解 找可行解的方案就是: 根据第一次建的图建一个反图..然后求逆拓扑排序,建反图的原因是保持冲突的两个事件肯定会被染成不同的颜色 求逆拓扑排序的原因也是为了对图染的色不会发生冲突, ...

  4. poj3683 Priest John's Busiest Day

    2-SAT. 读入用了黄学长的快速读入,在此膜拜感谢. 把每对时间当作俩个点.如果有交叉代表相互矛盾. 然后tarjan缩点,这样就能得出当前的2-SAT问题是否有解. 如果有解,跑拓扑排序就能找出一 ...

  5. POJ3683 Falsita

    http://poj.org/problem?id=3683 思路:2-SAT,输出任意一组方案,O(m+n) #include<cstdio> #include<iostream& ...

  6. 【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 ...

  7. Poj3683:Priest John's Busiest Day

    题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然 ...

  8. POJ3683 Priest John's Busiest Day(2-SAT)

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11049   Accepted: 3767   Special Judge ...

  9. poj3683(2-SAT 求任意方案)

    基础的2-SAT求任意方案的题目. Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

随机推荐

  1. spring之bean

    Bean的基本配置 id属性 id属性确定bean的唯一标识符,容器对bean的管理,访问,以及该bean的依赖关系,都通过该属性来完成.bean的id属性在Spring容器中应该是唯一的. clas ...

  2. [JavaWeb]SpringSecurity-OAuth2.0 统一认证、资源分离的配置,用于分布式架构、模块化开发的认证体系

    前言 关于 OAuth2.0的认证体系,翻阅了好多资料,RCF 文档太多,看了一半就看不下去了,毕竟全英文的文档看起来,是有一点让我烦躁,但也对 OAuth2.0的认证流程有了一个基本的概念,之前用 ...

  3. Entity Framework查询注意

    首先我们看下where的方法,直接查看定义(定义如下),其实一种是对IEnumerable的扩展,一种是对IQueryable的扩展,直接看最常用的,其实区别就在IEnumerable的扩展的参数是系 ...

  4. SAP RFC函数远程调试跟踪管理软件

    最近在搞OA系统与sap的接口开发,接口太多老是和.net的开发人员打嘴仗,为了避免不必要的纠结,自己做了一个rfc的调试工具,有些问题调试起来也比较容易了.程序是delphi开发的,为了保证程序可以 ...

  5. C#如何向word文档插入一个新段落及隐藏段落

    编辑Word文档时,我们有时会突然想增加一段新内容:而将word文档给他人浏览时,有些信息我们是不想让他人看到的.那么如何运用C#编程的方式巧妙地插入或隐藏段落呢?本文将与大家分享一种向Word文档插 ...

  6. Python 基础 一

    Python 基础  一 一.关于Python的介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum),这一两年在国内很流行,应用很广泛. 二.Python的基础知识(1) 1 ...

  7. lxml简明教程

    最近要做下微信爬虫,之前写个小东西都是直接用正则提取数据就算了,如果需要更稳定的提取数据,还是使用 xpath 定位元素比较可靠.周末没事,从爬虫的角度研究了一下 python xml 相关的库. P ...

  8. sql关键字之null

    在数据库中使用一种特殊的值表示未知的值--NULL,我们称之为空值但并不是空的字符串,而是特殊的值.

  9. Hush Framework框架配置

    在写这篇文章的时候,楼主已经饿的不行了,因为我从3点开始就在折腾Hush Framework,走了很多弯路,打铁要趁热,先把基本的过程记录下来,留待以后翻阅,同时记录其中容易走弯路的地方,特别是对于一 ...

  10. Git下载、更新、提交使用总结

    Git使用总结 1.下载代码到本地 1.1指定存储文件路径 1.运行git-bash.exe 2.指定盘符:cd f:work 1.2下载代码 命令:$ git clone <版本库的网址> ...