JZOJ8.17(C组)外星人入侵

来源:互联网 发布:mysql远程管理工具 编辑:程序博客网 时间:2024/05/02 06:09
题目:

外星人入侵地球。可怕的吃人外星人正在全国各地依次序建立它们的基地。


全国共有N(1≤ 10,000)座城市,城市编号1N。城市之间有M(0≤ 100,000)条双向道路相连。外星人计划建立A(0AN)个基地。


你只有在距离当前所有外星人基地至少K(1K100)单位长度的城市才能得到安全。


所以你必须赶快写一个程序决定走到哪里去。


分析:

看到题目是图论专题,就想用图论算法(第一题就这么被坑死了),不过这题的确要用图论算法,用了SPFA,但是用了边集数组存储法,一个maxn*maxn的record直接无情爆内存。后来听说要用邻接表,一用果然是正确的,内存问题解决了,但是时间问题又来了。听课前用的是没做一次SPFA就统计一次有多少个城市可以逃,并把被外星人攻占的城市标记。但是这样效率低下,改成了用一个ANS,一开始是ANS=N,后来每找到一个距离小于AILEN的点就DEC一下ANS,当ANS被DEC到0时,后面就可以直接全输出了,不必再占时间,这样优化后可以过(400多MS)。总的就是SPFA+按题意的优化。


附上代码:

const
  maxn=20000;

type node=record
     fromv,endv,v:longint;
     next:longint;
end;

var
  a:array [1..maxn*10] of node;
  f,last:array [1..maxn] of longint;
  flag,v1:array [1..maxn] of boolean;
  data:array [1..maxn*10] of longint;
  n,m,temp,alien,bj,ans:longint;

procedure work(x,y,z:longint);
begin
  inc(bj);
  a[bj].fromv:=x;
  a[bj].endv:=y;
  a[bj].v:=z;
  a[bj].next:=last[x];
  last[x]:=bj;
end;

procedure init;
var
  i,x,y,z:longint;
begin
  readln(n,m,temp,alien);
  for i:=1 to m do
    begin
      readln(x,y,z);
      work(x,y,z);
      work(y,x,z);
    end;
end;

procedure spfa(s:longint);
var
  i,head,tail:longint;
begin
  fillchar(f,sizeof(f),$7f);
  fillchar(v1,sizeof(v1),false);
  head:=0;tail:=1;
  data[1]:=s;v1[s]:=true;f[s]:=0;
  repeat
    head:=head+1;
    i:=last[data[head]];
    while i<>0 do
      begin
        if f[a[i].fromv]+a[i].v<f[a[i].endv] then
          begin
            f[a[i].endv]:=f[a[i].fromv]+a[i].v;
            if not v1[a[i].endv] then
              begin
                inc(tail);
                data[tail]:=a[i].endv;
                v1[a[i].endv]:=true;
              end;
          end;
        i:=a[i].next;
      end;
    v1[data[head]]:=false;
  until head=tail;
end;

procedure main;
var
  i,j,num:longint;
begin
  ans:=n;
  for i:=1 to temp do
    begin
      readln(num);
      if ans=0 then
        begin
          writeln(0);
          continue;
        end;
      spfa(num);
      for j:=1 to n do
        if (flag[j]) or (f[j]<alien) then
          if not flag[j] then
            begin
              flag[j]:=true;
              dec(ans);
            end;
      writeln(ans);
    end;
end;

begin
  init;
  main;
end.

0 0
原创粉丝点击