POJ 3683 Priest John's Busiest Day(2-SAT输出方案)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sdz20172133/article/details/88083828

Priest John's Busiest Day

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 12491   Accepted: 4252   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 SiTi and DiSi 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

POJ Founder Monthly Contest – 2008.08.31, Dagger and Facer

题意:

n场婚礼,每场婚礼的开始时间为s,结束时间为t,每场婚礼有一个时间为d的仪式,这个仪式要么在开始的时刻开始,要么在最后开始(t-d开始),问能否安排每场婚礼举行仪式的时间,使主持人能参加所有的这些仪式的全过程。

分析:

我们设Xi可以第i场婚礼参加开头为1,不在开头(即参加结尾)为0

加边:参考:https://blog.csdn.net/V5ZSQ/article/details/47168479

如果Si~Si+Di 与 Sj~Sj+Dj冲突,则Xi->~Xj,Xj->~Xi 
如果Si~Si+Di 与 Tj -Dj~Tj冲突,则Xi->Xj,~Xj->~Xi 
如果Ti -Di~Ti 与 Sj~Sj+Dj冲突,则Xj->Xi,~Xi->~Xj 
如果Ti -Di~Ti 与 Tj -Dj~Tj冲突,则~Xi->Xj,~Xj->Xi 
 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<cmath>
using namespace std;
const int maxn=10000+10;
struct node
{
    int s,e,d;
    node(){}
    node(int s,int e,int d):s(s),e(e),d(d){}
}t[maxn];
int judge(int st1,int et1,int st2,int et2){
	if( et1 <= st2 ||et2 <= st1 )return 1;
	return 0;
}
struct TwoSAT
{
    int n;//原始图的节点数(未翻倍)
    vector<int> G[maxn*2];//G[i]==j表示如果mark[i]=true,那么mark[j]也要=true
    bool mark[maxn*2];//标记
    int S[maxn*2],c;//S和c用来记录一次dfs遍历的所有节点编号

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<2*n;i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }

    //加入(x,xval)或(y,yval)条件
    //xval=0表示假,yval=1表示真
    void add_clause(int x,int xval,int y,int yval)
    {
        x=x*2+xval;
        y=y*2+yval;
        G[x].push_back(y);
       // G[y^1].push_back(x);
    }

    //从x执行dfs遍历,途径的所有点都标记
    //如果不能标记,那么返回false
    bool dfs(int x)
    {
        if(mark[x^1]) return false;//这两句的位置不能调换
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<G[x].size();i++)
            if(!dfs(G[x][i])) return false;
        return true;
    }

    //判断当前2-SAT问题是否有解
    bool solve()
    {
        for(int i=0;i<2*n;i+=2)
        if(!mark[i] && !mark[i+1])
        {
            c=0;
            if(!dfs(i))
            {
                while(c>0) mark[S[--c]]=false;
                if(!dfs(i+1)) return false;
            }
        }
        return true;
    }
}TS;
int main()
{
	 int n,m;
	 int a,b,c,d;
	 char op[10];
	 while(scanf("%d",&n)!=-1)
	{
		TS.init(n);
		for(int i=0;i<n;i++)
		{
		  int sh,sm,eh,em,d;
          scanf("%d:%d %d:%d %d",&sh,&sm,&eh,&em,&d);
          t[i]=node(sh*60+sm,eh*60+em,d);
		}
		for(int i=0;i<n;i++)
      		for(int j=i+1;j<n;j++)
    	{
			if(judge(t[i].s,t[i].s+t[i].d,t[j].s,t[j].s+t[j].d)==0)
			{
				TS.add_clause(i,0,j,1);
				TS.add_clause(j,0,i,1);
			}
			if(judge(t[i].s,t[i].s+t[i].d,t[j].e-t[j].d,t[j].e)==0)
			{
				TS.add_clause(i,0,j,0);
				TS.add_clause(j,1,i,1);
			}
			if(judge(t[i].e-t[i].d,t[i].e,t[j].s,t[j].s+t[j].d)==0)
			{
				TS.add_clause(i,1,j,1);
				TS.add_clause(j,0,i,0);
			}
			if(judge(t[i].e-t[i].d,t[i].e,t[j].e-t[j].d,t[j].e)==0)
			{
				TS.add_clause(i,1,j,0);
				TS.add_clause(j,1,i,0);
			}
    	}
		if(!TS.solve()) printf("NO\n");
		else
    	{
        	printf("YES\n");
        	for(int i=0;i<n;i++)
       		 {
       		    // cout<<TS.mark[i*2]<<endl;
            	if(TS.mark[i*2])
               	 printf("%02d:%02d %02d:%02d\n",t[i].s/60,t[i].s%60,(t[i].s+t[i].d)/60,(t[i].s+t[i].d)%60);
            	else
                	printf("%02d:%02d %02d:%02d\n",(t[i].e-t[i].d)/60,(t[i].e-t[i].d)%60,t[i].e/60,t[i].e%60);
        	}
    	}

	}
	 return 0;


}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/88083828