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 ...
随机推荐
- visual studio 2005 编fortran程序,运行后dos窗口显示问题
比如程序: program main implicit none write(*,*) "AAAAAAAAAAAAAAAAAAAAAAAA" stop end 虽然可以看见DOS窗 ...
- linux 查看系统状态方法
Linux下如何查看系统启动时间和运行时间 1.uptime命令输出:16:11:40 up 59 days, 4:21, 2 users, load average: 0.00, 0.01, 0.0 ...
- 【转】 Update和FixedUpdate的区别
MonoBehaviour.Update 更新 当MonoBehaviour启用时,其Update在每一帧被调用. MonoBehaviour.FixedUpdate 固定更新 当MonoBehavi ...
- 點擊按鈕后彈出新頁面導致原頁面CSS失效
比方说在页面里面有个LinkButton,要点击以后要打开新窗口,而且新窗口的URL是根据用户选择结果动态产生的.LinkButton的代码这样写: protected void Service ...
- Qt之窗体拖拽、自适应分辨率、自适应大小 good
Qt之自定义界面(实现无边框.可移动) Qt之自定义界面(窗体缩放-跨平台终极版) Qt之自定义界面(窗体缩放) http://blog.csdn.net/liang19890820/article/ ...
- node.js事件触发
var events = require('events'); var EventEmitter = events.EventEmitter(); //监听这个名为TestE事件 EventEmitt ...
- 创建第一个ArcGIS API for Silverlight应用
原文:创建第一个ArcGIS API for Silverlight应用 在完成前面的开发环境搭建以后,接下来实现我们的第一个ArcGIS API forSilverlight应用程序. 接下来我们一 ...
- ArcGIS API for Silverlight 点沿着线流动
原文:ArcGIS API for Silverlight 点沿着线流动 概述 前段时间做了一个项目,要求是有一些电力输送线,电力输送线或者石油管道都是有流动方向的,用户想做一个动态效果来模拟电力的输 ...
- How to disable and clear query ranges in sysquery form
query = new query('Query name'); queryBuildDataSource = query.dataSourceTable(tableNum('table name') ...
- Ubuntu 14.04安装OpenCV 3.1
从OpenCV官网上下载OpenCV官网上下载OpenCV的未编译源代码: 点击这里 国内很多网络打开OpenCV官网速度缓慢,可以点击如下地址直接从GitHub上下载OpenCV 3.1的源代码 下 ...