poj3683(2-SAT 求任意方案)
基础的2-SAT求任意方案的题目。
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 求任意方案)的更多相关文章
- 求任意长度数组的最大值(整数类型)。利用params参数实现任意长度的改变。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- P1474 货币系统 Money Systems(完全背包求填充方案数)
题目链接:https://www.luogu.org/problemnew/show/1474 题目大意:有V种货币,求用V种货币凑出面值N有多少种方案. 解题思路:就是完全背包问题,只是将求最大价值 ...
- 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 ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路
Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- 利用arguments求任意数量数字的和/最大值/最小值
文章地址 https://www.cnblogs.com/sandraryan/ arguments是函数内的临时数据,用完销毁,有类似于数组的操作,但不是数组. 举个栗子1:利用arguments求 ...
- dfs+记忆化搜索,求任意两点之间的最长路径
C.Coolest Ski Route 题意:n个点,m条边组成的有向图,求任意两点之间的最长路径 dfs记忆化搜索 #include<iostream> #include<stri ...
- JS求任意字符串中出现最多的字符以及出现的次数
我爱撸码,撸码使我感到快乐!大家好,我是Counter本节讲讲如何利用JS来查找任意给定的字符串,求字符串中出现次数最多的字符,出现的次数.直接上代码了,该注释的都注释啦.非常轻松加愉快.效果如下: ...
- HDU1850 尼姆博弈求可行方案数目
尼姆博弈(Nimm's Game) 题型 尼姆博弈模型,大致上是这样的: 有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜. 分析 1.首先自己想一下 ...
- hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解
题意:有一棵n个点的树,点之间用无向边相连.现把这棵树对应一个序列,这个序列任意两点的距离为这两点在树上的距离,显然,这样的序列有n!个,加入这是第i个序列,那么这个序列所提供的贡献值为:第一个点到其 ...
随机推荐
- Jboss as 服务器基本设置
http://www.cnblogs.com/lovingprince/archive/2009/09/03/2166307.html Step one: download JBoss Applica ...
- Linux命令-网络命令:mail
root用户发送邮件 mail wangyunpeng 给wangyunpeng发送邮件,wangyunpeng不在线也可以收到发送的邮件 wangyunpeng用户接收邮件 mail 接收邮件 he ...
- ubuntu安装Skype 4.3
Install Skype 4.3 Step 1: Remove previous version sudo apt-get remove skype skype-bin:i386 skype:i38 ...
- Oracle学习-Power Designer、visio 2003、Oracle sql developer、OEM、expdp
Oracle的体系太庞大了.对于刚開始学习的人来说,难免有些无从下手的感觉. 经过一学期的学习对Oracle学习有了一些深入的了解,由于之前学习过Oracle的一些主要的知识.所以学习起来上手比較快一 ...
- 4~20mA模拟输出(电流环)应用笔记(转)
https://zm12.sm-tc.cn/?src=http%3A%2F%2Fwww.aichengxu.com%2Fview%2F5397788&uid=d2f68cd7fd230c162 ...
- 用 php 实现一个视图组件和模板引擎——基础
只要不是做后端接口开发和一些作为守护进程之类的服务器脚本,大多数时候都是在和浏览器打交道,因此合理组织并展现 html 标签是最为常见的工作.一般大家使用框架时,都会自带有一套视图组件和模板引擎. 我 ...
- [k8s]简单启动一个k8s集群
简单启动一个k8s集群 kube-master mkdir -p /root/logs/api-audit /root/logs/controller /root/logs/scheduler kub ...
- C#多线程方法同步
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- java 发送带Basic Auth认证的http post请求实例代码
构造http header private static final String URL = "url"; private static final String APP_KEY ...
- python-sqlite3之占位符
The sqlite3 module supports two kinds of placeholders: question marks (qmark style) and named placeh ...