poj 3683

来源:互联网 发布:淘宝的盈利模式 编辑:程序博客网 时间:2024/05/21 17:47

一个小镇里面只有一个牧师,同时镇里有多对情侣要举办婚礼,婚礼中有一个仪式必须要牧师主持,仪式可以有两个时间可以选择。牧师每次只能主持一个婚礼。求解一个方案,使得每对情侣都得以举办婚礼。

枚举每两对情侣,根据两个时间的冲突关系建图,然后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;
}

原创粉丝点击