codevs1002

题目地址:http://codevs.cn/problem/1002/

分析:

这道题目针对于第一问很明显是Flood_Fill,也就是DFS(不过要注意拓展八个方向)
   第二问就是最小生成树,统计最小生成树最多的边以及每条边的权值
   然后就AC了。。。
   这里注意!
      ①数组不能开50*50,要开1000*1000,出题人坑爹- -
      ②在一条边上即为可搭桥,否则权值为INF
   主要考察的就是选手的细心程度以及对搜索,最小生成树的掌握程度

代码:

const  maxr=52;maxe=3010;

type
  tnode=record
    a,b,c:integer;
  end;
tmap=array[0.. maxr+1,0.. maxr+1] of integer;


var
r,c:integer;
map:tmap;
n,e:integer;
erc:array[1.. maxe] of tnode;
f:array[1 .. maxe] of integer;
resulta,resultb:integer;


procedure getinfo;
var i,j:integer;
ch:char;
begin
readln(r, c);
for i:=1 to r do 
  begin
  for j:=1 to c do 
    begin
      read(ch);
      if ch='.' then map[i,j]:=0 
      else map[i,j]:=-1;
    end;
  readln;
  end;
end;


procedure getvex(x,y:integer);
var i,h,t:integer;
dx,dy,nx,ny:integer;
q:array[1 .. maxe, 1 .. 2] of integer;
begin
h:=0; 
t:=1; 
q[1,1]:=x; 
q[1,2]:=y;
inc(n); //n是建筑物的总数
map[x,y]:=n;  //map[x,y]是什么含义?
repeat
  inc(h);
  for dx:=-1 to 1 do
  for dy:=-1 to 1 do 
    if (dx<>0) or (dy<>0) then 
      begin
      nx:=q[h,1]+dx; 
      ny:=q[h,2]+dy;
      if map[nx,ny]<>-1 then continue;
      map[nx,ny]:=n;
      inc(t); 
      q[t,1]:=nx;
      q[t,2]:=ny;
      end;
until h=t;
end;


procedure inserterc(a,b,c:integer);
begin
if (a=0) or (b=0) or (a=b) then exit;
inc(e); 
erc[e].a:=a; 
erc[e].b:=b; 
erc[e].c:=c;
end;


procedure init;
var
last,i,j:integer;
point:array[0..  maxr, 0 .. maxr] of integer;
begin
n:=0;
for i:= 1 to r do
for j:= 1 to c do 
   if map[i, j]=-1 then getvex(i, j);
fillchar(point, sizeof(point), 0);
for i:= 1 to r do
for j:= 1 to c do 
   if map[i, j]<>0 then 
     begin
     point[i,j]:=map[i,j];
     point[i-1,j]:=map[i,j];
     point[i, j-1]:=map[i,j];
     point[i-1,j-1] := map[i, j];
     end;
for i := 0 to r do
   begin
    last := -1;
    for j := 0 to c do
      if point[i, j] <> 0 then begin
        if last <> -1 then
          inserterc(point[i, last], point[i, j], j - last);
        last := j;
    end;
  end;
  for j := 0 to c do 
    begin
    last := -1;
    for i := 0 to r do
      if point[i, j] <> 0 then 
        begin
        if last <> -1 then
          inserterc(point[last, j], point[i, j], i - last);
        last := i;
        end;
    end;
  for i := 1 to n do f[i] := -1;
end;


procedure sift(s, t : integer);
var
  i, j : integer;
  tmp : tnode;
begin
  i := s; j := i + i; tmp := erc[i];
  while j <= t do 
    begin
    if (j < t) and (erc[j + 1].c > erc[j].c) then inc(j);
    if tmp.c >= erc[j].c then break;
    erc[i] := erc[j];
    i := j; j := i + i;
    end;
  erc[i] := tmp;
end;


procedure sort;
var
swap:tnode;
i:integer;
begin
for i:=e shr 1 downto 1 do 
sift(i, e);
for i:=e downto 2 do 
  begin
  swap:=erc[i]; 
  erc[i]:=erc[1]; 
  erc[1]:=swap;
  sift(1,i-1);
  end;
end;


function root(v : integer) : integer;
var
tmp,t:integer;
begin
t:=v;
while f[t]>0 do t:=f[t];
root:=t;
while f[v]>0 do 
  begin
  tmp:=f[v];
  f[v]:=t;
  v:=tmp;
  end;
end;


procedure merge(x, y : integer);
var
swap:integer;
begin
if -f[x]<-f[y] then 
  begin
  swap:=x; 
  x:=y; 
  y:=swap;
  end;
f[x]:=f[x]+f[y];
f[y]:=x;
end;


procedure main;
var
a,b,i:integer;
begin
resulta:=0; 
resultb:=0;
for i:= 1 to e do 
  begin
  a:=root(erc[i].a); 
  b:=root(erc[i].b);
  if a<>b then 
    begin
    inc(resulta); inc(resultb, erc[i].c);
    merge(a, b)
    end;
  end;
end;


procedure print;
begin
writeln(n);
writeln(resulta, ' ', resultb);
end;


begin
  getinfo;
  init;
  sort;
  main;
  print;
end.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值