基础的2-SAT求任意方案的题目。

Priest John's Busiest Day
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7309   Accepted: 2492   Special Judge

Description

John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old legend in the town that the couple who get married on that day will be forever blessed by the God of Love. This year N couples plan to get married on the blessed day. The i-th couple plan to hold their wedding from time Si to time Ti. According to the traditions in the town, there must be a special ceremony on which the couple stand before the priest and accept blessings. The i-th couple need Di minutes to finish this ceremony. Moreover, this ceremony must be either at the beginning or the ending of the wedding (i.e. it must be either from Si to Si + Di, or from Ti - Di to Ti). Could you tell John how to arrange his schedule so that he can present at every special ceremonies of the weddings.

Note that John can not be present at two weddings simultaneously.

Input

The first line contains a integer N ( 1 ≤ N ≤ 1000).
The next N lines contain the Si, Ti and Di. Si and Ti are in the format of hh:mm.

Output

The first line of output contains "YES" or "NO" indicating whether John can be present at every special ceremony. If it is "YES", output another N lines describing the staring time and finishing time of all the ceremonies.

Sample Input

2
08:00 09:00 30
08:15 09:00 20

Sample Output

YES
08:00 08:30
08:40 09:00

Source

 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#include <queue>
#include <sstream>
#include <iostream>
using namespace std;
#define INF 0x3fffffff
#define N 2020 struct node
{
int from,to,next;
}edge[N*N]; int n;
int b[N],d[N],k[N];
int stk[N],vis[N],low[N],link[N],mark[N];
int top,index,id,du[N];//记录入度数
int pre[N],cnt,g[N];// g 用来记录排序后的结果 int g1[N]; //用来记录缩点后的每一个点所含的点 int check(int x,int y,int x1,int y1)
{
if( y<=x1 || x>=y1 )
return ;
return ;
} void dfs(int s)
{
mark[s]=;
vis[s]=index++;
low[s]=vis[s];
stk[top++]=s;
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if(mark[v]==) dfs(v);
if(mark[v]==) low[s]=min(low[s],low[v]);
}
if(low[s]==vis[s])
{
int tmp;
id++;
do
{
tmp=stk[top-];
link[tmp]=id;
mark[tmp]=-;
}while(stk[--top]!=s);
}
} void add_edge(int u,int v)
{
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].next=pre[u];
pre[u]=cnt++;
} void topsort()
{
memset(mark,,sizeof(mark));
top=;
int tcnt=;
for(int i=;i<=id;i++)
if(du[i]==)
{
mark[i]=;
stk[top++]=i;//把这个节点入栈
g[tcnt++]=i;
}
while(top!=)
{
int cur=stk[--top];
for(int p=pre[cur];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if(mark[v]==) continue;
du[v]--;
if(du[v]==)
{
mark[v]=;
stk[top++]=v;
g[tcnt++]=v;
}
}
}
//排好了序 } void dfs1(int s)
{
mark[s]=-; //表示这个点不可以选
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v=edge[p].to;
dfs1(v);
}
} int main()
{
//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","w",stdout);
while(~scanf("%d",&n))
{
cnt=;
memset(pre,-,sizeof(pre));
for(int i=;i<n;i++)
{
int x,y,x1,y1,w;
scanf("%d:%d %d:%d %d",&x,&y,&x1,&y1,&w);
x=x*+y;
x1=x1*+y1;
b[i]=x; d[i]=x1;
k[i]=w; //分别记录可以用的第一次和第二次
}
for(int i=;i<n;i++)
{
for(int j=i+;j<n;j++)
{
if( check(b[i],b[i]+k[i],b[j],b[j]+k[j]) ) //判断是否有相交部分.
{
add_edge(*i,*j+);
add_edge(*j,*i+);
}
if( check(b[i],b[i]+k[i],d[j]-k[j],d[j]) )
{
add_edge(*i,*j);
add_edge(*j+,*i+);
}
if( check(d[i]-k[i],d[i],b[j],b[j]+k[j]))
{
add_edge(*i+,*j+);
add_edge(*j,*i);
}
if( check(d[i]-k[i],d[i],d[j]-k[j],d[j]))
{
add_edge(*i+,*j);
add_edge(*j+,*i);
}
}
}
//构好了图 ,然后就是判断是否可行然后求出可行解
top=index=id=;
memset(mark,,sizeof(mark));
for(int i=;i<*n;i++)
if(mark[i]==)
dfs(i);
int flag=;
for(int i=;i<*n;i+=)
{
if(link[i]==link[i+])
{
flag=;
break;
}
} if(flag)
{
printf("NO\n");
}
else
{
printf("YES\n");
//关键的时候,怎么找出所有的可行解
// 先构建一张逆图先
int tcnt=cnt;//重新构建一张图
memset(g1,,sizeof(g1)); cnt=;
memset(pre,-,sizeof(pre));
for(int i=;i<*n;i++)
{
g1[ link[i] ]=i;
} memset(du,,sizeof(du));
for(int i=;i<tcnt;i++)
{
int x=edge[i].from;
int y=edge[i].to;
if(link[x] != link[y])
{
add_edge(link[y],link[x]);//建逆图
du[ link[x] ]++;
} //g1[ link[x] ]
}
//然后就是topsort了
topsort();
memset(mark,,sizeof(mark)); for(int i=;i<id;i++) //从最低层开始
{
if(mark[ g[i] ]!=-)//表示这个点可以选
{
mark[ g[i] ]=;
//将所有对立可能的点全部标记为不能去
int key=g1[ g[i] ];
key=key^;
key=link[key]; //对立点所缩成的一个点
dfs1(key);
}
} for(int i=;i<n;i++)
{
if(mark[ link[*i] ]==)
{
int x,y,x1,y1;
x=b[i]/;
y=b[i]%;
x1=(b[i]+k[i])/;
y1=(b[i]+k[i])%;
printf("%02d:%02d %02d:%02d\n",x,y,x1,y1);
}
else
{
int x,y,x1,y1;
x=(d[i]-k[i])/;
y=(d[i]-k[i])%;
x1=(d[i])/;
y1=(d[i])%;
printf("%02d:%02d %02d:%02d\n",x,y,x1,y1);
}
}
}
}
return ;
}

poj3683(2-SAT 求任意方案)的更多相关文章

  1. 求任意长度数组的最大值(整数类型)。利用params参数实现任意长度的改变。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. P1474 货币系统 Money Systems(完全背包求填充方案数)

    题目链接:https://www.luogu.org/problemnew/show/1474 题目大意:有V种货币,求用V种货币凑出面值N有多少种方案. 解题思路:就是完全背包问题,只是将求最大价值 ...

  3. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  4. 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  5. 利用arguments求任意数量数字的和/最大值/最小值

    文章地址 https://www.cnblogs.com/sandraryan/ arguments是函数内的临时数据,用完销毁,有类似于数组的操作,但不是数组. 举个栗子1:利用arguments求 ...

  6. dfs+记忆化搜索,求任意两点之间的最长路径

    C.Coolest Ski Route 题意:n个点,m条边组成的有向图,求任意两点之间的最长路径 dfs记忆化搜索 #include<iostream> #include<stri ...

  7. JS求任意字符串中出现最多的字符以及出现的次数

    我爱撸码,撸码使我感到快乐!大家好,我是Counter本节讲讲如何利用JS来查找任意给定的字符串,求字符串中出现次数最多的字符,出现的次数.直接上代码了,该注释的都注释啦.非常轻松加愉快.效果如下: ...

  8. HDU1850 尼姆博弈求可行方案数目

    尼姆博弈(Nimm's Game) 题型 尼姆博弈模型,大致上是这样的: 有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜. 分析 1.首先自己想一下 ...

  9. hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解

    题意:有一棵n个点的树,点之间用无向边相连.现把这棵树对应一个序列,这个序列任意两点的距离为这两点在树上的距离,显然,这样的序列有n!个,加入这是第i个序列,那么这个序列所提供的贡献值为:第一个点到其 ...

随机推荐

  1. mysql union和union all 的差别以及使用

    Union由于要进行反复值扫描,所以效率低.假设合并没有刻意要删除反复行,那么就使用Union All  两个要联合的SQL语句 字段个数必须一样.并且字段类型要"相容"(一致). ...

  2. 《转》oracle—flashback

    FLASHBACK介绍 在介绍flashback之前先介绍下undo_retention相关参数 undo_retention:表示undo数据的过期时间.系统默认这个时间设置为900即15分钟.但要 ...

  3. AES + RSA + Hash 实现 C-S 安全交互

    概述 AES 由于其执行速度快,易于硬件实现,破解难度大等优势,被广泛用于数据的加密. 既然是对称加密,那如何保证秘钥的安全传输?很容易想到用 RSA 加密秘钥.由于只能用私钥解密,而私钥不需要交互双 ...

  4. mysql事务块处理

    begin ,rollback,commit .当然有的人用begin /begin work .推荐用START TRANSACTION 是SQL-99标准启动一个事务. start transac ...

  5. 悟道—位IT高管20年的职场心经(读书笔记一)

    悟道--一位IT高管20年的职场心经 第一章  修炼! 修炼! 别跟我谈事业,先把工作做好. 别跟我说理想,先把饭碗端好: 志不可天天立.道必须日日修.没有实力,一切皆为妄谈. 修炼是硬道理. 1.1 ...

  6. Chrome应用技巧之颜色拾取

    之前在Chrome应用店找了个插件实现拾色功能.并且很不理想.不知道是不是曾经Chrome自带的开发工具没提供到拾色功能还是我没发现.今天无意中发现Chomer自带的开发工具可拾色,请看以下的GIF动 ...

  7. JavaNIO - AbstractInterruptibleChannel

    1. 描述 可异步关闭和中断的Channel. (1)实现InterruptibleChannel接口的Channel支持异步关闭:如果一个线程IO阻塞在一个可中断的channel,另一个线程可以执行 ...

  8. RocketMQ综述(未完成)

    RocketMQ是一款分布式.队列模型的消息中间件,具有以下特点: 1.能够保证严格的消息顺序 2.提供丰富的消息拉取模式 3.高效的订阅者水平扩展能力 4.实时的消息订阅机制 5.亿级消息堆积能力 ...

  9. 关于mysql内存表的一个帖子(转载)

    地址:http://bbs.csdn.net/topics/360030699 引用楼主 zgycsmb 的回复:问:1mysql的内存表性能怎么样2mysql的内存表与system v 这种共享内存 ...

  10. eclipse配置代码自动补全auto-completion

    你如果使用的是JAVA EE的模式,就这样配置: 1. Window>Preferences>Java>Editor>Content Assist>Auto Activa ...