一个小镇里面只有一个牧师,同时镇里有多对情侣要举办婚礼,婚礼中有一个仪式必须要牧师主持,仪式可以有两个时间可以选择。牧师每次只能主持一个婚礼。求解一个方案,使得每对情侣都得以举办婚礼。
枚举每两对情侣,根据两个时间的冲突关系建图,然后2—sat求解即可。
AC代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
int const maxn=2002;
int first[maxn],rfirst[maxn],dfn[maxn],low[maxn],sta[maxn],tar[maxn],D[maxn],sC[maxn][2],eC[maxn][2],ret[maxn],flag[maxn],in[maxn];
int size,rsize,cnt,index,N;
stack<int> S;
struct Edge
{
int v,next;
}edge[maxn*maxn],redge[maxn*maxn];
void rinsert(int u,int v)
{
redge[rsize].v=v;
redge[rsize].next=rfirst[u];
rfirst[u]=rsize++;
}
void insert(int u,int v)
{
edge[size].v=v;
edge[size].next=first[u];
first[u]=size++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++index;
S.push(u); sta[u]=1;
for(int e=first[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(sta[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int v=-1; cnt++;
while(v!=u)
{
v=S.top(); S.pop();
tar[v]=cnt; sta[v]=0;
}
}
}
void slove()
{
memset(dfn,0,sizeof(dfn));
memset(sta,0,sizeof(sta));
for(int i=0;i<2*N;i++)
if(!dfn[i]) tarjan(i);
}
int check()
{
for(int i=0;i<N;i++)
if(tar[2*i]==tar[2*i+1])
return 0;
return 1;
}
void print(int t)
{
int h=t/60,m=t%60;
printf("%02d:%02d",h,m);
}
void topsort()
{
for(int i=0;i<cnt;)
for(int j=1;j<=cnt;j++)
if(!in[j])
{
in[j]--; ret[i++]=j;
for(int e=rfirst[j];e!=-1;e=redge[e].next)
in[redge[e].v]--;
}
memset(flag,0,sizeof(flag));
for(int i=0;i<cnt;i++)
{
for(int j=0;j<2*N;j++)
if(tar[j]==ret[i] && !flag[j^1])
flag[j]=1;
}
for(int i=0;i<2*N;i++)
if(flag[i])
{
if(i%2)
{
print(eC[i/2][1]); printf(" "); print(eC[i/2][0]); printf("\n");
}
else
{
print(sC[i/2][0]); printf(" "); print(sC[i/2][1]); printf("\n");
}
}
}
void build()
{
for(int u=0;u<N;u++)
for(int v=u+1;v<N;v++)
{
if((sC[u][0]-sC[v][1])*(sC[u][1]-sC[v][0])<0)
{
insert(2*u,2*v+1); insert(2*v,2*u+1);
}
if((sC[u][0]-eC[v][0])*(sC[u][1]-eC[v][1])<0)
{
insert(2*u,2*v); insert(2*v+1,2*u+1);
}
if((eC[u][1]-sC[v][1])*(eC[u][0]-sC[v][0])<0)
{
insert(2*u+1,2*v+1); insert(2*v,2*u);
}
if((eC[u][0]-eC[v][1])*(eC[u][1]-eC[v][0])<0)
{
insert(2*u+1,2*v); insert(2*v+1,2*u);
}
}
}
int main()
{
// freopen("test.txt","r",stdin);
memset(first,-1,sizeof(first)); size=0;
memset(rfirst,-1,sizeof(rfirst)); rsize=0;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
int h1,h2,m1,m2,d;
scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&d);
sC[i][0]=h1*60+m1; sC[i][1]=sC[i][0]+d;
eC[i][0]=h2*60+m2; eC[i][1]=eC[i][0]-d;
}
build(); slove();
if(!check()) printf("NO\n");
else
{
memset(in,0,sizeof(in));
for(int u=0;u<2*N;u++)
for(int e=first[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
if(tar[u]!=tar[v])
{
rinsert(tar[v],tar[u]);
in[tar[u]]++;
}
}
printf("YES\n");
topsort();
}
return 0;
}