Pku 2749 Building roads

7 篇文章 0 订阅
6 篇文章 0 订阅

题目:

 Building roads

来源:

 Pku 2749

题目大意:

 有两个中转站,和N个点。每个点要么连到1号中转站,要么连到2号中转站。给出一  些限制信息,即哪两个点必须连到一个中转站上,哪两个点必须不能连到一个中转站  上,求任意两个中转站间最大的距离最小。

数据范围:

 2 <= N <= 500, 0 <= A <= 1000, 0 <= B <= 1000,坐标[-1000000, 1000000]

样例:

 4 1 1
 12750 28546 15361 32055
 6706 3887
 10754 8166
 12668 19380
 15788 16059
 3 4
 2 3
53246

做题思路:

 做这道题发现大数组+记录型的变量直接赋值,直接TLE

 把X点连到1号中转站上设为I点,连到2号中转站上设为I'点。
 把Y点连到1号中转站上设为J点,连到2号中转站上设为J'点。
 四种构图方式:
 1) Add(I,J'),Add(J,I')
 2) Add(I',J),Add(J',I)
 3) Add(I,J),Add(J',I')
 4) Add(I',J'),Add(J,I)
 对于题目中的输入信息,当两个点必须连到一个中转站上时,使用3,4号构图方  式。  当两个点必须不连到一个中转站上时,使用1,2号构图方式。
 设Dis1[I]代表I到1号中转站的距离,Dis2[I]代表I到2号中转站的距离,D代表中转站  之间的距离,每次二分答案Ans。
 若Dis1[I]+Dis1[J]>Ans,使用1号构图方式
 若Dis2[I]+Dis2[J]>Ans,使用2号构图方式
 若Dis1[I]+Dis2[J]+D>Ans,使用3号构图方式
 若Dis2[I]+Dis1[J]+D>Ans,使用4号构图方式。

知识点:

 2-sat、kosaraju、构图

type
 act=record
 y,next:longint;
 end;
var
 a1,a2:array[0..1000000]of act;
 b:array[0..500,0..500]of boolean;
 first1,first2,q,f,dist1,dist2,f1,f2:array[0..10000]oflongint;
 tot1,tot2,n,d,ans,time,p1,p2:longint;
//============================================================
procedure build1(x,y:longint);
begin
 inc(tot1);
 a1[tot1].y:=y;
 a1[tot1].next:=first1[x];
 first1[x]:=tot1;
end;
//=====================================================================
procedure build2(x,y:longint);
begin
 inc(tot2);
 a2[tot2].y:=y;
 a2[tot2].next:=first2[x];
 first2[x]:=tot2;
end;
//===================================================================
procedure init;
var
 i,x1,x2,y1,y2,x,y,a,bi,j:longint;
begin
 fillchar(first1,sizeof(first1),0);
 fillchar(first2,sizeof(first2),0);
 fillchar(b,sizeof(b),false);
 tot1:=0;tot2:=0;
 readln(n,a,bi);
 readln(x1,y1,x2,y2);
 d:=abs(x1-x2)+abs(y1-y2);
 fori:=1 to n do
  begin
  readln(x,y);
  dist1[i]:=abs(x-x1)+abs(y-y1);
  dist2[i]:=abs(x-x2)+abs(y-y2);
  end;
 fori:=1 to a do
  begin
  readln(x,y);
  b[x,y]:=true;b[y,x]:=true;
  build1(x*2,y*2-1);build2(y*2-1,x*2);
  build1(y*2,x*2-1);build2(x*2-1,y*2);
  build1(x*2-1,y*2);build2(y*2,x*2-1);
  build1(y*2-1,x*2);build2(x*2,y*2-1);
  end;
 fori:=1 to bi do
  begin
  readln(x,y);
  b[x,y]:=true;b[y,x]:=true;
  build1(x*2,y*2);build2(y*2,x*2);
  build1(y*2,x*2);build2(x*2,y*2);
  build1(x*2-1,y*2-1);build2(y*2-1,x*2-1);
  build1(y*2-1,x*2-1);build2(x*2-1,y*2-1);
  end;
 p1:=tot1;p2:=tot2;
 f1:=first1;f2:=first2;
end;
//============================================================
procedure dfs1(x:longint);
var
 t:longint;
begin
 f[x]:=1;
 t:=first1[x];
 whilet>0 do
  begin
   iff[a1[t].y]=0 then dfs1(a1[t].y);
  t:=a1[t].next;
  end;
 inc(time);
 q[time]:=x;
end;
//================================================================
procedure dfs2(x:longint);
var
 t:longint;
begin
 f[x]:=time;
 t:=first2[x];
 whilet>0 do
  begin
   iff[a2[t].y]=0 then dfs2(a2[t].y);
  t:=a2[t].next;
  end;
end;
//==============================================================
function kosaraju(x:longint):boolean;
var
 i,j:longint;
begin
 tot1:=p1;tot2:=p2;{<注意每次二分判定是要还原边表>}
 first1:=f1;first2:=f2;
 fori:=1 to n-1 do
  forj:=i+1 to n do
   ifnot b[i,j] then
   begin
     ifdist1[i]+dist1[j]>x then
     begin
      build1(i*2-1,j*2);build2(j*2,i*2-1);
      build1(j*2-1,i*2);build2(i*2,j*2-1);
     end;
     ifdist2[i]+dist2[j]>x then
     begin
      build1(i*2,j*2-1);build2(j*2-1,i*2);
      build1(j*2,i*2-1);build2(i*2-1,j*2);
     end;
     ifdist1[i]+d+dist2[j]>x then
     begin
      build1(i*2-1,j*2-1);build2(j*2-1,i*2-1);
      build1(j*2,i*2);build2(i*2,j*2);
     end;
     ifdist1[j]+d+dist2[i]>x then
     begin
      build1(j*2-1,i*2-1);build2(i*2-1,j*2-1);
      build1(i*2,j*2);build2(j*2,i*2);
     end;
   end;
 fillchar(f,sizeof(f),0);
 fillchar(q,sizeof(q),0);
 time:=0;
 fori:=1 to 2*n do
  iff[i]=0 then dfs1(i);
 fillchar(f,sizeof(f),0);
 time:=0;
 fori:=2*n downto 1 do
  iff[q[i]]=0 then
  begin
   inc(time);
   dfs2(q[i]);
   end;
 fori:=1 to n do
  iff[i*2]=f[i*2-1] then exit(false);
 exit(true);
end;
//======================================================================
procedure main;
var
 l,r:longint;
begin
 l:=0;r:=4000001;{<最大距离4000000超了就输出-1>}
 whilel<r do
  ifkosaraju((l+r)shr 1) then r:=(l+r)shr 1
   elsel:=(l+r)shr 1+1;
 ifl>4000000 then writeln('-1') else
 writeln(l);
end;
//=================================================================
begin
 init;
 main;
end.
 
题目来源: http://poj.org/problem?id=2749

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值