基础的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. 用nodepad++生成导入数据的SQL

    在工作中经常要往数据库里导入数据,如果是在本地,可以用SQL SERVER自带的工具 直接往表里导入或者 用ssis 导入 线上的数据库由dba负责,作为开发不能直接操作,需要程序员来生成sql语句, ...

  2. 【转载】XGBoost调参

    General Parameters: Guide the overall functioning Booster Parameters: Guide the individual booster ( ...

  3. REP-20147 Cannot implement column link for this detail SQL query. Converting to group link.

    注:本文为原创,作为学习交流使用,转载请标明作者及出处,作者保留追究法律责任的权力. Lumen Su lzsu1989#gmail.com (#=@) www.cnblogs.com/lzsu198 ...

  4. LNMP架构

    LNMP架构介绍 lnmp里的php会启动一个服务,nginx把用户请求的php交给php-fpm处理,比如登录网站php要和mysql做交互,查用户的账号和密码,处理完之后,php-fpm会告诉ng ...

  5. AHM ---301重定向

    使用amh.conf 或重新创建一个test.conf配置文件 .保存目录 /usr/local/nginx/conf/rewrite 例如跳到 www.shuaixingkeji.com if ($ ...

  6. Build System 和Test Framework overview总结

    良好的自动化系统可以帮助Dev/Tester快速发现product/test code issue. 正好上一个项目结束,上个项目在自动化系统上面做得非常好.从产品开始时半年release一次到后面每 ...

  7. 【Android界面实现】View Animation 使用介绍

        转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992     我们能够使用view animation 动画系统来给View控件加入tween动画(下称& ...

  8. springboot admin server常用配置

    Property name Description Default value spring.boot.admin.context-path The context-path prefixes the ...

  9. 在 Linux 客户端配置基于 Kerberos 身份验证的 NFS 服务器

    在这篇文章中我们会介绍配置基于 Kerberos 身份验证的 NFS 共享的整个流程.假设你已经配置好了一个 NFS 服务器和一个客户端.如果还没有,可以参考 安装和配置 NFS 服务器[2] - 它 ...

  10. dmesg命令应用

    昨晚上线服务的时候,看log偶然发现服务在启动半小时左右就会被supervise重新拉起,也没有core.通过重新启动的服务发现内存飙涨,且持续增加,怀疑是内存打满,进程被kill了. 其实怀疑是正确 ...