2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683
| Time Limit: 2000MS | Memory Limit: 65536K | |||
| Total Submissions: 8170 | Accepted: 2784 | 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
方法一:tarjan缩点+拓扑排序
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"vector"
#include"stack"
#include"map"
#define inf 0x3f3f3f3f
#define M 2009
using namespace std;
struct node
{
int u,v,next;
}edge[M*M*5];
stack<int>q;
struct EDGE
{
int v;
EDGE(int vv)
{
v=vv;
}
};
vector<EDGE>Edge[M];
int t,head[M],low[M],dfn[M],belong[M],num,index,use[M],n,degree[M],Color[M],fp[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void tarjan(int u)
{
low[u]=dfn[u]=++index;
q.push(u);
use[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(use[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
num++;
int vv;
do
{
vv=q.top();
q.pop();
use[vv]=0;
belong[vv]=num;
}while(vv!=u);
}
}
int psq(int n)
{
int i;
num=index=0;
memset(use,0,sizeof(use));
memset(dfn,0,sizeof(dfn));
for(i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(i=1;i<=n;i++)
if(belong[i]==belong[i+n])
return 0;
return 1;
}
struct Time
{
int l,r;
}time[M];
int ok(Time a,Time b)
{
if(a.r<=b.l||b.r<=a.l)
return 0;
return 1;
}
int op(int u)
{
if(u<=n)
return n+u;
else
return u-n;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=-1)
{
for(i=1;i<=n;i++)
{
int h1,h2,m1,m2,d;
scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&d);
time[i].l=h1*60+m1;
time[i].r=h1*60+m1+d;
time[i+n].l=h2*60+m2-d;
time[i+n].r=h2*60+m2;
}
init();
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(ok(time[i],time[j]))
{
add(i,j+n);
add(j,i+n);
}
if(ok(time[i],time[j+n]))
{
add(i,j);
add(j+n,i+n);
}
if(ok(time[i+n],time[j]))
{
add(i+n,j+n);
add(j,i);
}
if(ok(time[i+n],time[j+n]))
{
add(i+n,j);
add(j+n,i);
}
}
}
if(psq(n))//拓扑排序输出可行解
{
printf("YES\n");
memset(degree,0,sizeof(degree));//缩点的入度
memset(Color,0,sizeof(Color));//染色
for(i=0;i<t;i++)
{
int u=edge[i].u;
int v=edge[i].v;
fp[belong[u]]=belong[op(u)];//记录当前点所在的联通块与对应点所在联通块的相互影射
fp[belong[op(u)]]=belong[u];
if(belong[u]!=belong[v])
{
Edge[belong[v]].push_back(EDGE(belong[u]));//缩点建图,若不在同一个连通块则建立反边
degree[belong[u]]++;
}
}
queue<int>q;
for(i=1;i<=num;i++)
if(degree[i]==0)q.push(i);//入度为0的点入队
while(!q.empty())
{
int u=q.front();
q.pop();
if(Color[u]==0)//对未着色的点着色同时把对立点所在连通块着为相反的颜色
{
Color[u]=1;
Color[fp[u]]=-1;
}
for(i=0;i<(int)Edge[u].size();i++)
{
int v=Edge[u][i].v;
if(--degree[v]==0)
q.push(v);
}
}
for(i=1;i<=n;i++)
{
if(Color[belong[i]]==1)//连通块标记为1的是可行解
printf("%02d:%02d %02d:%02d\n",time[i].l/60,time[i].l%60,time[i].r/60,time[i].r%60);
else
printf("%02d:%02d %02d:%02d\n",time[i+n].l/60,time[i+n].l%60,time[i+n].r/60,time[i+n].r%60);
}
for(i=1;i<=num;i++)
Edge[i].clear();
}
else
printf("NO\n");
}
}方法二:dfs+枚举(字典序最小)
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"vector"
#include"stack"
#include"map"
#define inf 0x3f3f3f3f
#define M 2009
using namespace std;
struct node
{
int u,v,next;
}edge[M*M*5];
stack<int>q;
struct EDGE
{
int v;
EDGE(int vv)
{
v=vv;
}
};
vector<EDGE>Edge[M];
int t,head[M],low[M],dfn[M],belong[M],num,index,use[M],color[M],s[M],cnt,n,degree[M],Color[M],fp[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
struct Time
{
int l,r;
}time[M];
int ok(Time a,Time b)
{
if(a.r<=b.l||b.r<=a.l)
return 0;
return 1;
}
int op(int u)
{
if(u<=n)
return n+u;
else
return u-n;
}
int dfs(int u)
{
if(color[u]==1)
return 1;
if(color[u]==-1)
return 0;
s[cnt++]=u;
color[u]=1;
color[op(u)]=-1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!dfs(v))
return 0;
}
return 1;
}
int slove(int n)
{
int i,j;
memset(color,0,sizeof(color));
for(i=1;i<=2*n;i++)
{
if(color[i])continue;
cnt=0;
if(!dfs(i))
{
for(j=0;j<cnt;j++)
color[s[j]]=color[op(s[j])]=0;
if(!dfs(op(i)))
return 0;
}
}
return 1;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=-1)
{
for(i=1;i<=n;i++)
{
int h1,h2,m1,m2,d;
scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&d);
time[i].l=h1*60+m1;
time[i].r=h1*60+m1+d;
time[i+n].l=h2*60+m2-d;
time[i+n].r=h2*60+m2;
}
init();
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(ok(time[i],time[j]))
{
add(i,j+n);
add(j,i+n);
}
if(ok(time[i],time[j+n]))
{
add(i,j);
add(j+n,i+n);
}
if(ok(time[i+n],time[j]))
{
add(i+n,j+n);
add(j,i);
}
if(ok(time[i+n],time[j+n]))
{
add(i+n,j);
add(j+n,i);
}
}
}
if(slove(n))
{
printf("YES\n");
for(i=1;i<=n;i++)
{
if(color[i]==1)
printf("%02d:%02d %02d:%02d\n",time[i].l/60,time[i].l%60,time[i].r/60,time[i].r%60);
if(color[i+n]==1)
printf("%02d:%02d %02d:%02d\n",time[i+n].l/60,time[i+n].l%60,time[i+n].r/60,time[i+n].r%60);
}
for(i=1;i<=num;i++)
Edge[i].clear();
} else
printf("NO\n");
}
}
2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683的更多相关文章
- poj 3683 2-sat问题,输出任意一组可行解
/* 2sat问题 输出任意一组可行解 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #in ...
- HDU 1507 Uncle Tom's Inherited Land*(二分匹配,输出任意一组解)
Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- poj 3648 2-sat 输出任意一组解模板
转载地址:http://blog.csdn.net/qq172108805/article/details/7603351 /* 2-sat问题,题意:有对情侣结婚,请来n-1对夫妇,算上他们自己共n ...
- 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)
https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...
- CF 274D Lovely Matrix 拓扑排序,缩点 难度:2
http://codeforces.com/problemset/problem/274/D 这道题解题思路: 对每一行统计,以小值列作为弧尾,大值列作为弧头,(-1除外,不连弧),对得到的图做拓扑排 ...
- BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序
题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...
- UVA 10305 Ordering Tasks(拓扑排序的队列解法)
题目链接: https://vjudge.net/problem/UVA-10305#author=goodlife2017 题目描述 John有n个任务,但是有些任务需要在做完另外一些任务后才能做. ...
- BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq
BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...
- Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding 拓扑排序
E. Tree Folding 题目连接: http://codeforces.com/contest/765/problem/E Description Vanya wants to minimiz ...
随机推荐
- php数据缓存
用php进行微信开发时,碰到access_token长久保存的问题,以前都是用框架里的Cache直接set.get一下就完了.现在没框架可用了,只好自己动手写一个cache暂时用. 这个Cache类用 ...
- Java List 如何传值
// 合并 List 中的相同数据行 // Source : tmpOrderEntryListBeanList // Target : resultOrderEntryListBeanList // ...
- Linux core 文件介绍
Linux core 文件介绍 http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html 1. core文件的简单介绍在一个 ...
- (转)js一道比较考验的题目
转载下别人曾经出过的一道面试题,此题是他出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多难只是因为大多面试者 ...
- php---apache的A/B测试
A/B测试 A/B测试是一种新兴的网页优化方法,可以用于增加转化率注册率等网页指标..A/B测试的目的在于通过科学的实验设计.采样样本代表性.流量分割与小流量测试等方式来获得具有代表性的实验结论,并确 ...
- ArcGIS Engine开发之旅01---产品组成、逻辑体系结构
原文:ArcGIS Engine开发之旅01---产品组成.逻辑体系结构 ArcGIS Engine 由两个产品组成: 面向开发人员的软件开发包(ArcGIS Engine Developer k ...
- [LeetCode]题解(python):061-Rotate list
题目来源 https://leetcode.com/problems/rotate-list/ Given a list, rotate the list to the right by k plac ...
- saltstack之(九)配置管理源码部署Nginx
场景:rpm包安装的nginx服务,无法满足定制模块的需求,故线上环境使用nginx源码进行安装.本片文章详细介绍如何使用saltstack的配置管理功能实现nginx软件的源码安装. 下载源码:pc ...
- Linux就这个范儿 第9章 特种文件系统
Linux就这个范儿 第9章 特种文件系统 http://book.douban.com/reading/32081222/ P326 有一种文件系统,根本不在磁盘上.这种文件系统就是大名顶顶的ram ...
- Android java判断字符串包含某个字符段(或替换)
String str = "; ) { System.out.println("包含该字符串"); }