【APIO2009】ATM

[Apio2009]Atm

Time Limit:15000MS Memory Limit:165536K
Total Submit:4 Accepted:4
Case Time Limit:1500MS

Description


Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道 路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也 就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

Output

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

Sample Input

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1 5
1 4
4
3
5
6

Sample Output

47

Hint

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

  方法:Tarjan缩点之后SPFA求最长路搞定。

  Q:SPFA不会出环挂掉么?

  A:都Tarjan了,哪里还有环……直接变成一棵树了……

  

  Q:为什么我在OJ上交会WA或者TLE……

  A:当时比赛貌似开8M系统栈,OJ无法给开这么大的……本机测试(fpc 2.4.2)每组数据都可以在0.4s内出解。

  附:APIO数据下载     http://www.apio.olympiad.org/2009/

Program Apio_2009_ATM;

type rec=record

               endv,next:longint;

end;



var edge,map:Array[1..500000]of rec;

    father2,dist,order,atm,money,v,dfn,low,stack,father:Array[1..500000]of longint;

    Instack,vis:array[1..500000]of boolean;

    q:Array[0..10000000]of longint;

    n,m,s,p,total,tot,index,module,ans:longint;



function min(a,b:longint):longint;

begin

  if a<b then exit(a);

  exit(b);

end;



procedure addedge(s,t:longint);

begin

  inc(total);

  edge[total].endv:=t;

  edge[total].next:=father[s];

  father[s]:=total;

end;



procedure addedge2(s,t:longint);

begin

  inc(total);

  map[total].endv:=t;

  map[total].next:=father2[s];

  father2[s]:=total;

end;



procedure init;

var i,a,b:longint;

begin

  fillchar(father,sizeof(father),$ff);

  readln(n,m);

  for i:=1 to m do

    begin

      readln(a,b);

      addedge(a,b);

    end;

  for i:=1 to n do readln(money[i]);

  readln(s,p);

  for i:=1 to p do read(atm[i]);

end;



procedure tarjan(x:longint);

var p:longint;

begin

  inc(index);

  dfn[x]:=index;

  low[x]:=index;

  Instack[x]:=true;

  inc(tot);

  stack[tot]:=x;

  p:=father[x];

  while p>0 do

    begin

      if dfn[edge[p].endv]=0 then

        begin

          tarjan(edge[p].endv);

          low[x]:=min(low[x],low[edge[p].endv]);

        end

      else if instack[edge[p].endv] then

        low[x]:=min(low[x],dfn[edge[p].endv]);

      p:=edge[p].next;

    end;

  if dfn[x]=low[x] then

    begin

      inc(module);

      repeat

        order[stack[tot]]:=module;

        Instack[stack[tot]]:=false;

        dec(tot);

      until stack[tot+1]=x;

    end;

end;



procedure BuildNewGraph;

var i,p:longint;

begin

  fillchar(father2,sizeof(father2),$ff);

  for i:=1 to n do inc(v[order[i]],money[i]);

  total:=0;

  for i:=1 to n do

    begin

      p:=father[i];

      while p>0 do

        begin

          if order[i]<>order[edge[p].endv] then   addedge2(order[i],order[edge[p].endv]);

          p:=edge[p].next;

        end;

    end;

end;



procedure compress;

var i:longint;

begin

  fillchar(dfn,sizeof(dfn),0);

  fillchar(low,sizeof(low),0);

  fillchar(Instack,sizeof(Instack),false);

  tot:=0;index:=0;

  for i:=1 to n do

    if dfn[i]=0 then Tarjan(i);

  BuildNewGraph;

end;



procedure spfa(s:longint);

var head,tail,p,now:longint;

begin

  fillchar(vis,sizeof(vis),false);

  head:=0;tail:=0;

  q[head]:=s;vis[s]:=true;

  dist[s]:=v[s];

  while head<=tail do

    begin

      now:=q[head];

      p:=father2[now];

      while p>0 do

        begin

          if dist[map[p].endv]<dist[now]+v[map[p].endv] then

            begin

              dist[map[p].endv]:=dist[now]+v[map[p].endv];

              if not vis[map[p].endv] then

                begin

                  vis[map[p].endv]:=true;

                  tail:=(tail+1)mod 10000000;

                  q[tail]:=map[p].endv;

                end;

            end;

          p:=map[p].next;

        end;

      head:=(head+1)mod 10000000;

      vis[now]:=false;

    end;

end;



procedure Print;

var i:longint;

begin

  for i:=1 to p do

    if dist[order[atm[i]]]>ans then ans:=dist[order[atm[i]]];

  writeln(ans);

end;



begin

  init;

  Compress;

  spfa(order[s]);

  Print;

end.


你可能感兴趣的:(api)