poj 3683 Priest John's Busiest Day 2_sat

题目大意

  有n个婚礼,每个婚礼有起始时间si,结束时间ti,还有一个主持时间ti,ti必须安排在婚礼的开始或者结束,主持由祭祀来做,但是只有一个祭祀,所以各个婚礼的主持时间不能重复,问你有没有可能正常的安排主持时间,不能输出no,能的话要输出具体的答案:即每个婚礼的主持时间段是什么样的。

 

分析

  把一个婚礼分成两个点,分别代表一场婚礼开头主持和结束主持(用分钟算)的时间。那么就把问题转换成了一个2-SAT问题。若两个点之间有冲突(也就是时间有重合)则连边(具体见程序)。然后就是裸的2-SAT输出问题了(我打了200+的tarjan+拓扑)(要把tarjan的数组设大一些)。

 

代码

type
  arr=record
    x,y,next:longint;
end;

var
  a,a1:array[1..2000000] of arr;
  f:array[0..2000] of boolean;
  ls,zan,g,con,b,c,co:array[0..2000] of longint;
  dfn,low:array[0..3000] of longint;
  x,y,z:array[0..5000] of longint;
  tot,sum,n,m:longint;
  i,j,k:longint;
  e,d:longint;
  cc:char;
  s:string;

procedure add(x,y:longint);
begin
  inc(e);
  a[e].x:=x;
  a[e].y:=y;
  a[e].next:=ls[x];
  ls[x]:=e;
end;

function min(x,y:longint):longint;
begin
  if x<y then exit(x)
         else exit(y);
end;

procedure dfs(x:longint);
var
  i:longint;
begin
  inc(d);
  dfn[x]:=d;
  low[x]:=d;
  inc(tot);
  zan[tot]:=x;
  f[x]:=true;
  i:=ls[x];
  while i>0 do
    with a[i] do
    begin
      if dfn[y]=0
        then begin
               dfs(y);
               low[x]:=min(low[x],low[y]);
             end
        else if f[y] then low[x]:=min(low[x],dfn[y]);
      i:=next;
    end;
  if low[x]=dfn[x] then
  begin
    inc(sum);
    repeat
      i:=zan[tot];
      dec(tot);
      f[i]:=false;
      g[i]:=sum;
    until i=x;
  end;
end;

procedure tarjan;
var
  i:longint;
begin
  fillchar(f,sizeof(f),0);
  for i:=1 to n*2 do
    if dfn[i]=0
      then
        dfs(i);
end;

procedure topsort;
var
  i,j,k:longint;
  head,tail:longint;
begin
  head:=0;
  tail:=0;
  fillchar(b,sizeof(b),0);
  for i:=1 to sum do
    if c[i]=0 then
      begin
        tail:=tail+1;
        b[tail]:=i;
      end;
  if tail=0 then exit;
  repeat
    head:=head+1;
    i:=ls[b[head]];
    while i<>0 do
      with a[i] do
        begin
          c[y]:=c[y]-1;
          if c[y]=0
            then
              begin
                tail:=tail+1;
                b[tail]:=y;
              end;
          i:=next;
        end;
  until tail=head;
end;

procedure set_b(r:longint);
var
  i,j,k:longint;
begin
  i:=ls[r];
  co[r]:=-1;
  while i>0 do
    with a[i] do
      begin
        if co[y]=0
          then set_b(y);
        i:=next;
      end;
end;

procedure set_r;
var
  i,j,k:longint;
begin
  for i:=1 to sum do
    if co[b[i]]=0
      then
        begin
          co[b[i]]:=1;
          set_b(con[b[i]]);
        end;
end;

procedure print;
var
  i,t1,t2:longint;
begin
  writeln('YES');
  for i:=1 to n do
  begin
    if co[g[i]]=1
      then begin
             t1:=x[i];
             t2:=x[i]+z[i];
           end
      else begin
             t1:=y[i]-z[i];
             t2:=y[i];
           end;
    if t1 div 60<10 then write(0);
    write(t1 div 60,':');
    if t1 mod 60<10 then write(0);
    write(t1 mod 60,' ');
    if t2 div 60<10 then write(0);
    write(t2 div 60,':');
    if t2 mod 60<10 then write(0);
    writeln(t2 mod 60);
  end;
end;

procedure work;
var
  i,j,k:longint;
begin
  for i:=1 to n do
    begin
      if g[i]=g[i+n] then
        begin
          writeln('NO');
          exit;
        end;
      con[g[i]]:=g[i+n];
      con[g[i+n]]:=g[i];
    end;
  fillchar(ls,sizeof(ls),0);
  fillchar(c,sizeof(c),0);
  a1:=a;
  fillchar(a,sizeof(a),0);
  j:=e;
  e:=0;
  for i:=1 to j do
    with a1[i] do
      if g[x]<>g[y] then
        begin
          add(g[y],g[x]);
          c[g[x]]:=c[g[x]]+1;
        end;
  topsort;
  set_r;
  print;
end;

function check(x,y,x1,y1:longint):boolean;
begin
  if (y<=x1) or (y1<=x) then exit(false);
  check:=true;
end;

procedure init;
var
  i,j,k:longint;
begin
  readln(n);
  for i:=1 to n do
    begin
      s:='';
      read(cc); s:=cc;
      read(cc); s:=s+cc;
      val(s,j);
      read(cc);
      s:='';
      read(cc); s:=cc;
      read(cc); s:=s+cc;
      val(s,k);
      x[i]:=j*60+k;
      read(cc);
      s:='';
      read(cc); s:=cc;
      read(cc); s:=s+cc;
      val(s,j);
      read(cc);
      s:='';
      read(cc); s:=cc;
      read(cc); s:=s+cc;
      val(s,k);
      y[i]:=j*60+k;
      read(z[i]);
      readln;
    end;
end;

begin
  init;
  for i:=1 to n-1 do
    for j:=i+1 to n do
      begin
        if check(x[i],x[i]+z[i],x[j],x[j]+z[j])
          then
            begin
              add(i,j+n);
              add(j,i+n);
            end;
        if check(x[i],x[i]+z[i],y[j]-z[j],y[j])
          then
            begin
              add(i,j);
              add(i+n,j+n);
            end;
        if check(y[i]-z[i],y[i],x[j],x[j]+z[j])
          then
            begin
              add(i+n,j+n);
              add(j,i);
            end;
        if check(y[i]-z[i],y[i],y[j]-z[j],y[j])
          then
            begin
              add(i+n,j);
              add(j+n,i);
            end;
      end;
  tarjan;
  work;
end.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值