APIO2009 抢掠计划

来源:互联网 发布:阿里云os系统怎么样 编辑:程序博客网 时间:2024/05/17 03:53

【题意】

给一张图,每个点有一个ATM机,而其中的部分点是酒吧(可作为终点)。

抢掠计划就是从起点(1号点)出发,到终点的途中,将ATM机中的钱抢走。

问最多能抢到多少钱。

【题解】

很显然,由于图可能有环,所以自然地想到了SCC+DP。

题目不难,但数据很大,堆栈会溢出。表示懒得模拟堆栈了。

【代码】

{$M 100000000}uses math;type  edge=record         x,y,next:longint;       end;var  e,ee:array[1..500000] of edge;  h,s,b,v,low,dfn,ans,aa,g,c,q,a:array[0..500000] of longint;  i,j,k,m,n,st,f,r,tans,tt,t,times,tot,xx,x,y,ttt:longint;procedure add(x,y:longint);  begin    inc(tt);    e[tt].x:=x;e[tt].y:=y;    e[tt].next:=h[x];h[x]:=tt;  end;procedure tarjan(x:longint);  var i,y:longint;  begin    inc(t);inc(times);    low[x]:=times;dfn[x]:=times;    v[x]:=1;s[t]:=x;    i:=h[x];    while i<>0 do    begin      y:=e[i].y;      if v[y]=0 then      begin        tarjan(y);        low[x]:=min(low[x],low[y]);      end;      if v[y]=1 then        low[x]:=min(low[x],dfn[y]);      i:=e[i].next;    end;    if dfn[x]=low[x] then    begin      inc(tot);      repeat        y:=s[t];dec(t);        b[y]:=tot;v[y]:=2;      until y=x;    end;  end;begin  assign(input,'atm15.in');reset(input);  readln(n,m);  for i:=1 to m do  begin    readln(x,y);    add(x,y);  end;  for i:=1 to n do    read(aa[i]);  readln(st,xx);  for i:=1 to xx do    read(c[i]);  tarjan(st);  ee:=e;ttt:=tt;  tt:=0;  fillchar(h,sizeof(h),0);  for i:=1 to ttt do  if (b[ee[i].x]<>b[ee[i].y])and(b[ee[i].x]<>0)and(b[ee[i].y]<>0) then  begin    add(b[ee[i].x],b[ee[i].y]);    inc(g[b[ee[i].y]]);  end;  for i:=1 to n do    inc(a[b[i]],aa[i]);  q[1]:=b[st];  f:=1;r:=1;  while f<=r do  begin    k:=q[f];    i:=h[k];    while i<>0 do    begin      y:=e[i].y;      dec(g[y]);      if g[y]=0 then      begin        inc(r);q[r]:=y;      end;      ans[y]:=max(ans[y],ans[k]+a[k]);      i:=e[i].next;    end;    inc(f);  end;  for i:=1 to xx do    if ans[b[c[i]]]+a[b[c[i]]]>tans then tans:=ans[b[c[i]]]+a[b[c[i]]];  writeln(tans);end.


原创粉丝点击