[POJ3683 Priest John's Busiest Day]

[关键字]:2-sat

[题目大意]:有n场婚礼,牧师可以在每场婚礼开始后的di分钟主持,也可以在结束前的di分钟主持,问是否有一种方案可以让牧师主持所有婚礼。

//=====================================================================================================

[分析]:2-sat求解方案的问题。把每场婚礼看成一组点(A,A'),然后对所有有矛盾的点处理:A->B'(A与B有矛盾)、A->B(A与B’有矛盾)……,然后利用2-sat求解,具体方法可见《由对称性解2-sat问题》

[代码]:

View Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#define MAXN 2100
using namespace std;

struct rec
{
int st,ed;
}p[MAXN];
int n,tot,sum;
int dfn[MAXN],low[MAXN],ops[MAXN],colour[MAXN],index[MAXN],belong[MAXN];
bool instack[MAXN];
vector<int> e[MAXN],dag[MAXN];

bool fright(int x,int y)
{
if (p[x].ed<=p[y].st || p[y].ed<=p[x].st) return 0; else return 1;
}

void Init()
{
scanf("%d",&n);
int a,b,c,d,t;
for (int i=0;i<n;i++)
{
scanf("%d:%d %d:%d %d",&a,&b,&c,&d,&t);
int t1=a*60+b;
int t2=c*60+d;
p[tot].st=t1,p[tot++].ed=t1+t;
p[tot].st=t2-t,p[tot++].ed=t2;
}
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
if (i!=j)
{
if (fright(2*i,2*j)) e[2*i].push_back(2*j+1);
if (fright(2*i,2*j+1)) e[2*i].push_back(2*j);
if (fright(2*i+1,2*j)) e[2*i+1].push_back(2*j+1);
if (fright(2*i+1,2*j+1)) e[2*i+1].push_back(2*j);
}
n=tot;
}

stack<int> s;
void tarjan(int u)
{
dfn[u]=low[u]=++tot;
s.push(u);
instack[u]=1;
int size=e[u].size();
for (int i=0;i<size;i++)
{
int v=e[u][i];
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else
if (instack[v]) low[u]=min(low[u],dfn[v]);
}
if (dfn[u]==low[u])
{
sum++;
int v;
do{
v=s.top();
s.pop();
instack[v]=0;
belong[v]=sum;
}while (v!=u);
}
}

void solve()
{
sum=tot=0;
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
for (int i=0;i<n;i++)
if (!dfn[i]) tarjan(i);
for (int i=0;i<n;i+=2)
if (belong[i]==belong[i+1])
{
printf("NO\n");
return;
}
else ops[belong[i]]=belong[i+1],ops[belong[i+1]]=belong[i];
printf("YES\n");
memset(index,0,sizeof(index));
for (int i=0;i<n;i++)
{
int size=e[i].size();
for (int j=0;j<size;j++)
{
int v=e[i][j];
if (belong[i]!=belong[v])
dag[belong[v]].push_back(belong[i]),index[belong[i]]++;
}
}
queue<int> q;
for (int i=1;i<=sum;i++)
if (index[i]==0) q.push(i);
memset(colour,0,sizeof(colour));
while (!q.empty())
{
int u=q.front();
q.pop();
if (colour[u]==0) colour[u]=1,colour[ops[u]]=-1;
int size=dag[u].size();
for (int i=0;i<size;i++)
if (--index[dag[u][i]]==0) q.push(dag[u][i]);
}
//for (int i=1;i<=sum;i++) printf("%d %d\n",i,ops[i]);
int a,b,c,d;
for (int i=0;i<n;i+=2)
if (colour[belong[i]]==1)
{
a=p[i].st/60;
b=p[i].st%60;
c=p[i].ed/60;
d=p[i].ed%60;
printf("%02d:%02d %02d:%02d\n",a,b,c,d);
}
else
{
a=p[i+1].st/60;
b=p[i+1].st%60;
c=p[i+1].ed/60;
d=p[i+1].ed%60;
printf("%02d:%02d %02d:%02d\n",a,b,c,d);
}
}

int main()
{
Init();
solve();
system("pause");
return 0;
}



你可能感兴趣的:(poj)