[POJ3683]Priest John's Busiest Day(2-SAT)

传送门

题目大意:一个牧师要给n个婚礼进行仪式,给定婚礼开始的时间和结束的时间,仪式可以在婚礼开始的时候进行,也可以在婚礼结束前进行,问牧师能否完成所有的婚礼仪式并输出方案。


还是经典的2-SAT模型,为什么呢,我们来分析:
首先,一场婚礼有两个时间可以选择,刚好对应2-SAT的两个对称点,其次我们需要满足所有的仪式进行,所以就出现了约束条件,那么2-SAT可以很好的解决他们。建图的话,如果两个时间段 i , j i,j i,j有重叠的话那么 i → j ′ , j → i ′ i\rightarrow j', j\rightarrow i' ij,ji


再补充一个不需要Topsort的易实现做法,我们知道Tarjan的本质是一个DFS,实际上构建了一颗DFS树。那么他在回溯的时候自底向上求取强连通分量,所以Tarjan算法下DFS树中越深的节点得到的强连通分量编号会越小,所以他本身已经满足了缩点后的有向无环图”自底向上“的拓扑序。 那么我们可以直接比较点i和他的对应点的强连通分量编号来染色(给点和对应点染上不同的颜色,注意自己明确什么颜色对应选/不选)

注意这题的输入输出处理比较麻烦。


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2100;
const int maxm=4000000;
struct AKCqhzdy
{
	int x,y,next;
}a[maxm]; int len,last[maxn];
int n;
void ins(int x,int y)
{
	len++; a[len].x=x;a[len].y=y;
	a[len].next=last[x];last[x]=len;
}
int id,top,scc;
int dfn[maxn],low[maxn];
int sta[maxn]; bool insta[maxn];
int bl[maxn];
void tarjan(int x)
{
	sta[++top]=x; insta[x]=true;
	low[x]=dfn[x]=++id;
	for(int k=last[x];k;k=a[k].next)
	{
		int y=a[k].y;
		if(dfn[y]==-1)
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(insta[y]) low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x])
	{
		scc++; int i;
		do{
			i=sta[top--];
			insta[i]=false;
			bl[i]=scc;
		}while(i!=x);
	}
}
struct OrzAKC
{
	int l,r,c;
}t[maxn];
struct Rose_max
{
	int x,y,next;
}b[maxm]; int last2[maxn],len2=0;
void ins2(int x,int y)
{
	len2++; b[len2].x=x; b[len2].y=y;
	b[len2].next=last2[x]; last2[x]=len2;
}
int pairs[maxm],col[maxm];

void build()
{
	memset(last,0,sizeof(last)); len=0;
	for(int i=1;i<n;i++)
	{
		int li1=t[i].l,ri1=t[i].l+t[i].c,li2=t[i].r-t[i].c,ri2=t[i].r;
		for(int j=i+1;j<=n;j++)
		{
			int lj1=t[j].l,rj1=t[j].l+t[j].c,lj2=t[j].r-t[j].c,rj2=t[j].r;
			if(li1<rj1 && lj1<ri1)
          	{  
			  	ins(2*i,2*j+1);
		     	ins(2*j,2*i+1);
          	}
	        if(li1<rj2 && lj2<ri1)
	        {  
				ins(2*i,2*j);
	            ins(2*j+1,2*i+1);
	        }
	        if(li2<rj1 && lj1<ri2)
	        {   
				ins(2*i+1,2*j+1);
	            ins(2*j,2*i);
	        }
	        if(li2<rj2 && lj2<ri2)
	        {   
				ins(2*j+1,2*i);
	            ins(2*i+1,2*j);
	        }
		}
	}
}
bool solve()
{
	int i;
    memset(dfn,-1,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(bl,-1,sizeof(bl));
    memset(insta,false,sizeof(insta));
    scc=id=top=0;
    for(i=1;i<=2*n;i++)
      	if(dfn[i]==-1)
	  		tarjan(i);
    for(i=1;i<=n;i++)
      	if(bl[2*i]==bl[2*i+1])
	  		return false;
    else
	{
		pairs[bl[2*i]]=bl[2*i+1];
        pairs[bl[2*i+1]]=bl[2*i];
	}
    return true;
}
void rebuild()
{
	memset(last2,0,sizeof(last2)); len2=0;
	for(int i=1;i<=len;i++)
	{
		if(bl[a[i].x] != bl[a[i].y] )
			ins2( bl[a[i].x] , bl[a[i].y]);
	}
}
void paint(int x)
{
	insta[x]=true;
	for(int k=last2[x];k;k=b[k].next)
	{
		int y=b[k].y;
		if(!insta[y]) paint(y);
	}
	if(col[x]==-1)
	{
		col[x]=1;
		col[pairs[x]]=0;
	}
}
void topsort()
{
	memset(col,-1,sizeof(col));
	memset(insta,false,sizeof(insta));
	for(int i=1;i<=scc;i++)
		if(!insta[i])
			paint(i);		
}
void print()
{  
	int i;
   	for (i=1;i<=n;i++)
	{
     	if (col[bl[2*i]]==1 )
	 	{
     	  	printf("%02d:%02d ",t[i].l/60,t[i].l%60);
     	  	printf("%02d:%02d\n",(t[i].l+t[i].c)/60,(t[i].l+t[i].c)%60);
     	}
     	else
		{
     	  	printf("%02d:%02d ",(t[i].r-t[i].c)/60,(t[i].r-t[i].c)%60);
 	      	printf("%02d:%02d\n",t[i].r/60,t[i].r%60);
     	}
    }
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int a,b,c,d;
		scanf("%d:%d%d:%d%d",&a,&b,&c,&d,&t[i].c);
		t[i].l=a*60+b,t[i].r=c*60+d;
	}
	build();
	if(!solve()) printf("NO\n");
	else
	{
		printf("YES\n");
		rebuild();
		topsort();
		print();
	}
	return 0;
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值