基础的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. Linux yum操作无效的解决方法

    1.没网,试着:ping www.baidu.com 如果显示没有连接的话,就说明没网,也就无法使用yum 命令. 2.ping通了的话,还是是用不了yum命令,说明是yum镜像没有了,那么就得下载一 ...

  2. ASP.Net 自定义HttpModule注册管道事件

    背景: 一个请求在到达处理器时 可能需要做很多重复的工作 比如使用固定的算法推算出用户id 角色   如果在应用程序各处做重复解析 会产生大量代码冗余 还有能想到的诸如记录访问者 应用日志 统计流量 ...

  3. mysql事务块处理

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

  4. 转: 利用RabbitMQ、MySQL实现超大用户级别的消息在/离线收发

    由于RabbitMQ中只有队列(queue)才能存储信息,所以用RabbitMQ实现超大用户级别(百万计)的消息在/离线收发需要对每一个用户创建一个永久队列. 但是RabbitMQ节点内存有限,经测试 ...

  5. MAC 通过brew安装软件

    1.安装brew ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/instal ...

  6. 读取properties属性文件——国际化

    public class PropertiesInfo { /** * PropertiesInfo实例 */ private static PropertiesInfo pi = null; pri ...

  7. 大话Web-Audio-Api

    大话Web-Audio-Api 转:https://www.jianshu.com/p/0079d1fe7496 简单的例子: <script> var context; var musi ...

  8. 【JavaScript】一个同步于本地时间的动态时间

    这样例很easy.了解JavaScript之后就是几行的代码便可以完毕的事情. 可是对于一些未接触过JavaScript的人来说,差点儿非常大project的样子.然后在网上苦苦寻觅代码,之后在茫茫的 ...

  9. 【未完成】junit简单使用

    参考资料: 一般使用:https://www.w3cschool.cn/junit/ 集成spring: https://www.cnblogs.com/faramita2016/p/7637086. ...

  10. emblog后台拿shell

    emlog版本:5.3.1 先本地弄好shell 新建一个文件夹,里面放shell,shell名称和文件名要一致.压缩为zip 然后在安装插件处上传. 成功后的路径content/plugins/te ...