POJ 3683 Priest John's Busiest Day(2-ST)

题目链接:http://poj.org/problem?id=3683

题意:有n个婚礼要举行,但是只有一个牧师。第i个婚礼使用牧师的时间长为leni,可以在开始时或结束时使用。问能否使得n个婚礼均举行?

思路:对于婚礼i,i*2-1表示在开始使用牧师,i*2表示在结束使用牧师。枚举每一对不同的i和j:

(1)如果i*2-1和j*2-1冲突。连接i*2-1  j*2

(2)如果i*2-1和j*2冲突,连接i*2-1 j*2-1

(3)如果i*2和j*2-1冲突,连接i*2 j*2

(4)如果i*2和j*2冲突,连接i*2 j*2-1

 

 #include <stdio.h>

 #include <string.h>

 #include <stack>

 #define min(x,y) ((x)<(y)?(x):(y))

 using namespace std;

 

 struct node

 {

     int v,next;

 };

 

 

 

 const int MAX=4005;

 const int MAXE=5000005;

 node edges[MAXE];

 int head[MAX],e;

 int dfn[MAX],low[MAX],visit[MAX],color[MAX],col[MAX];

 int n,index,cnt;

 stack<int> S;

 int deg[MAX],ans[MAX],p[MAX];

 int head1[MAX],e1;

 node edges1[MAXE];

 

 

 

 void Add(int u,int v)

 {

     edges[e].v=v;

     edges[e].next=head[u];

     head[u]=e++;

 }

 

 void Add1(int u,int v)

 {

     edges1[e1].v=v;

     edges1[e1].next=head1[u];

     head1[u]=e1++;

 }

 

 void Tarjan(int u)

 {

     int i,v;

 

     low[u]=dfn[u]=++index;S.push(u);visit[u]=1;

     for(i=head[u];i!=-1;i=edges[i].next)

     {

         v=edges[i].v;

         if(!dfn[v])

         {

             Tarjan(v);

             low[u]=min(low[u],low[v]);

         }

         else if(visit[v]) low[u]=min(low[u],dfn[v]);

     }

     if(dfn[u]==low[u])

     {

         cnt++;

         do

         {

             v=S.top();

             S.pop();

             visit[v]=0;

             color[v]=cnt;

         }while(u!=v);

     }

 }

 

 void init()

 {

     memset(deg,0,sizeof(deg));

     memset(head1,-1,sizeof(head1));

     e1=0;

     int i,u,v,x,y;

     for(u=1;u<=2*n;u++)

     {

         for(i=head[u];i!=-1;i=edges[i].next)

         {

             v=edges[i].v;

             if(color[v]!=color[u])

             {

                 x=color[v];

                 y=color[u];

                 Add1(x,y);

                 deg[y]++;

             }

         }

     }

     while(!S.empty()) S.pop();

     for(i=1;i<=cnt;i++) if(!deg[i]) S.push(i);

     memset(p,0,sizeof(p));

     while(!S.empty())

     {

         u=S.top();

         S.pop();

         if(!p[u]) p[u]=1,p[col[u]]=-1;

         for(i=head1[u];i!=-1;i=edges1[i].next)

         {

             v=edges1[i].v;

             if(--deg[v]==0) S.push(v);

         }

     }

     memset(ans,0,sizeof(ans));

     for(i=1;i<=n;i++)

     {

         if(p[color[i*2-1]]==1) ans[i]=1;

     }

 }

 

 int TWO_ST()

 {

     int i;

 

     memset(dfn,0,sizeof(dfn));

     memset(visit,0,sizeof(visit));

     index=cnt=0;

     while(!S.empty()) S.pop();

     for(i=1;i<=2*n;i++) if(!dfn[i]) Tarjan(i);

     for(i=1;i<=n;i++)

     {

         if(color[i*2-1]==color[i*2]) return 0;

         col[color[i*2-1]]=color[i*2];

         col[color[i*2]]=color[i*2-1];

     }

     init();

     return 1;

 }

 

 struct Node

 {

     int s,e,len;

 };

 

 Node a[MAX];

 

 void deal()

 {

     if(!TWO_ST())

     {

         puts("NO");

         return;

     }

     puts("YES");

     int i,x,y;

     for(i=1;i<=n;i++)

     {

         ans[i]?(x=a[i].s,y=a[i].s+a[i].len):(x=a[i].e-a[i].len,y=a[i].e);

         printf("%02d:%02d %02d:%02d\n",x/60,x%60,y/60,y%60);

     }

 }

 

 

 

 int OK(int s1,int len1,int s2,int len2)

 {

     return s1<s2+len2&&s2<s1+len1;

 }

 

 int main()

 {

     while(scanf("%d",&n)!=-1)

     {

         int i,j,h1,m1,h2,m2;

         for(i=1;i<=n;i++)

         {

             scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&a[i].len);

             a[i].s=h1*60+m1;

             a[i].e=h2*60+m2;

         }

         memset(head,-1,sizeof(head));

         e=0;

         int u,v;

         for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j)

         {

             if(OK(a[i].s,a[i].len,a[j].s,a[j].len)) Add(i*2-1,j*2);

             if(OK(a[i].s,a[i].len,a[j].e-a[j].len,a[j].len)) Add(i*2-1,j*2-1);

             if(OK(a[i].e-a[i].len,a[i].len,a[j].s,a[j].len)) Add(i*2,j*2);

             if(OK(a[i].e-a[i].len,a[i].len,a[j].e-a[j].len,a[j].len)) Add(i*2,j*2-1);

         }

         deal();

     }

     return 0;

 }

 

  

 

 

你可能感兴趣的:(poj)