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 ...
随机推荐
- 【转】Cocos2d - 观察者模式NotificationCenter
http://shahdza.blog.51cto.com/2410787/1611575 [唠叨] 观察者模式 也叫订阅/发布(Subscribe/Publish)模式,是 MVC( 模型-视图-控 ...
- Medusa: Gauges for JavaFX
Medusa: Gauges for JavaFX https://community.oracle.com/docs/DOC-992746
- FTS抓包看AVDTP
1.概述 测试过程为打开Audio连接,没有听音乐,人后断开Audio连接,主要目的是为了测试AVDTP的工作流程. 2.Frame分析 首先贴出抓取的关于AVDTP的包: 在L2CAP ...
- MySQL- 锁(3)
InnoDB在不同隔离级别下的一致性读及锁的差异 前面讲过,锁和多版本数据是InnoDB实现一致性读和ISO/ANSI SQL92隔离级别的手段,因此,在不同的隔离级别下,InnoDB处理SQL时采用 ...
- TCP粘包
一.通信协议TCP/UDP: TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.客户端和服务器端都要有一一成对的socket, 因此 ...
- yii2 实现多表联查
- 设计模式:享元模式(Flyweight)
定 义:运用共享技术有效地支持大量细粒度的对象. 结构图: 内部状态:在享元对象内部并且不会随环境而改变的共享部分. 外部状态:随环境改变而改变的.不可共享的状态. Flyweight类,具体享元 ...
- oracle截取某个字符前面的字符串
已验证. 要求:A.数据库表中的一个字符串 可能含有"+" 例:ORC+001 也可能不含“+” B.要求如果该字符串含有“+”,则取“+”之前的字符 例:ORC+001 取ORC ...
- 【转】Android的材料设计兼容库(Design Support Library)
转自:http://www.jcodecraeer.com/a/anzhuokaifa/developer/2015/0531/2958.html?mType=Group Android的材料设计兼容 ...
- mybatis的xlm的sql
<sqlMap namespace="egis.scms.order"> <typeAlias alias="ScmsOrderDTO" ...