poj 2749 Building roads s-SAT判定+二分

题意:有n个牛棚, 还有两个中转站S1和S2, S1和S2用一条路连接起来。 为了使得任意牛棚两个都可以有道路联通,现在要让每个牛棚都连接一条路到S1或者S2。

有a对牛棚互相有仇恨,所以不能让他们的路连接到同一个中转站。还有b对牛棚互相喜欢,所以他们的路必须连到同一个中专站。

道路的长度是两点的曼哈顿距离。

问最小的任意两牛棚间的距离中的最大值是多少?


分析:首先二分最大距离,然后建图:

一、若两点的某种选择的连接方式使得这两点间的距离大于最大距离则矛盾,然后加边。

二、根据仇恨情况和喜欢情况加边。


不知道为什么在poj上AC了在hdu上却WA了。表示不能理解咯。


代码:

var
  e,n,a1,b1,x1,x2,y1,y2,tot,f1:longint;
  x,y:array[1..500] of longint;
  a,b:array[1..1000,1..2] of longint;
  side:array[1..1000000] of record
    x,y,next:longint;
  end;
  belong,last,f:array[1..2000] of longint;
  v:array[1..2000] of boolean;

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

procedure init;
var
  i:longint;
begin
  readln(n,a1,b1);
  readln(x1,y1,x2,y2);
  for i:=1 to n do
    readln(x[i],y[i]);
  for i:=1 to a1 do
    readln(a[i,1],a[i,2]);
  for i:=1 to b1 do
    readln(b[i,1],b[i,2]);
end;

procedure build(mid:longint);
var
  s,i,j:longint;
begin
  e:=0;
  fillchar(last,sizeof(last),0);
  for i:=1 to a1 do
  begin
    add(a[i,1],a[i,2]+n);
    add(a[i,1]+n,a[i,2]);
    add(a[i,2],a[i,1]+n);
    add(a[i,2]+n,a[i,1]);
  end;
  for i:=1 to b1 do
  begin
    add(b[i,1],b[i,2]);
    add(b[i,1]+n,b[i,2]+n);
    add(b[i,2],b[i,1]);
    add(b[i,2]+n,b[i,1]+n);
  end;
  s:=abs(x1-x2)+abs(y1-y2);
  for i:=1 to n-1 do
    for j:=i+1 to n do
    begin
      if abs(x[i]-x1)+abs(y[i]-y1)+abs(x[j]-x1)+abs(y[j]-y1)>mid then
      begin
        add(i,j+n);
        add(j,i+n);
      end;
      if abs(x[i]-x2)+abs(y[i]-y2)+abs(x[j]-x2)+abs(y[j]-y2)>mid then
      begin
        add(i+n,j);
        add(j+n,i);
      end;
      if abs(x[i]-x1)+abs(y[i]-y1)+abs(x[j]-x2)+abs(y[j]-y2)+s>mid then
      begin
        add(i,j);
        add(j+n,i+n);
      end;
      if abs(x[i]-x2)+abs(y[i]-y2)+abs(x[j]-x1)+abs(y[j]-y1)+s>mid then
      begin
        add(i+n,j+n);
        add(j,i);
      end;
    end;
end;

procedure dfs(x:longint);
var
  i:longint;
begin
  v[x]:=false;
  i:=last[x];
  while i>0 do
    with side[i] do
    begin
      if v[y] then dfs(y);
      i:=next;
    end;
  if tot=0
    then begin
           inc(f1);
           f[f1]:=x;
         end
    else belong[x]:=tot;
end;

procedure kosaraju;
var
  i:longint;
begin
  tot:=0;
  f1:=0;
  fillchar(v,sizeof(v),true);
  for i:=1 to n*2 do
    if v[i] then dfs(i);
  fillchar(last,sizeof(last),0);
  for i:=1 to e do
    add(side[i].y,side[i].x);
  fillchar(v,sizeof(v),true);
  for i:=n*2 downto 1 do
    if v[f[i]] then
    begin
      inc(tot);
      dfs(f[i]);
    end;
end;

procedure main;
var
  l,r,mid,ans,i:longint;
  flag:boolean;
begin
  l:=0;
  r:=4000000;
  ans:=maxlongint;
  while l<=r do
  begin
    mid:=(l+r) div 2;
    build(mid);
    kosaraju;
    flag:=true;
    for i:=1 to n do
      if belong[i]=belong[i+n] then
      begin
        flag:=false;
        break;
      end;
    if flag
      then begin
             if mid<ans then ans:=mid;
             r:=mid-1;
           end
      else l:=mid+1;
  end;
  if ans=maxlongint then ans:=-1; 
  writeln(ans);
end;

begin
  init;
  main;
end.


你可能感兴趣的:(poj 2749 Building roads s-SAT判定+二分)