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个序列,那么这个序列所提供的贡献值为:第一个点到其 ...
随机推荐
- 【PHP】组合条件搜索SQL
前端html多个搜索条件组合 后台一个sql语句,很方便和简洁:仅提供思路. 也可以配合着进行分页操作,非常赞~
- docker build 的 cache 机制
cache 机制注意事项 可以说,cache 机制很大程度上做到了镜像的复用,降低存储空间的同时,还大大缩短了构建时间.然而,不得不说的是,想要用好 cache 机制,那就必须了解利用 cache 机 ...
- CVTE电话面试
Cvte电话面试 1. SVM和逻辑回归的相同不同点 2. 特征值和奇异值的区别 3. 如何找到全局最优解,梯度下降和牛顿法区别 4. 防止过拟合的方法 5. 随机森林和ADBOOST方差和偏置 6. ...
- LNMP架构
LNMP架构介绍 lnmp里的php会启动一个服务,nginx把用户请求的php交给php-fpm处理,比如登录网站php要和mysql做交互,查用户的账号和密码,处理完之后,php-fpm会告诉ng ...
- Powershell - 获取OS版本信息和catpion信息
Environment 获取 OSversion: $OSVersion = [System.Environment]::OSVersion.Version WMI获取Caption: $OSCap ...
- 如何在mysql下实现事务的提交与回滚
最近要对数据库的数据进行一个定时迁移,为了防止在执行过程sql语句因为某些原因报错而导致数据转移混乱,因此要对我们的脚本加以事务进行控制. 首先我们建一张tran_test表 CREATE TABLE ...
- Newton's method Drawback and advantage
Newton Raphson Method: Advantages and Drawbacks: v=QwyjgmqbR9s" target="_blank"& ...
- 编译JDK1.7
1. 背景 想要一探JDK内部的实现机制,最便捷的路径之一就是自己编译一套JDK. 2. 获取JDK源码 从http://openjdk.java.net/下载源码,如 openjdk-6-src-b ...
- 跟着百度学PHP[17]-复习PDO的几个关键词
主要就是复习一下几个关键词.发现太久没有写又忘了.惭愧. final self static const
- libubox-uloop
参考:libubox组件(3)——uloop uloop是提供事件驱动机制接口,类似libevent事件框架,基于epoll接口来实现的. uloop三大功能:事件管理(uloop_fd).超时管理( ...