P1179: [Apio2009]Atm

缩点+spfa最短路,因为最终不可能有环,所以直接spfa。

  1 const maxe=1000001;
  2 type
  3   node=record
  4     f,t:longint;
  5   end;
  6 var n,m,s,i,j,ans,cnt,num,u,x,dgr:longint;
  7 h,he,dfn,low,q,d,v,va,bl:array[0..maxe] of longint;
  8 b,bi:array[0..maxe] of node;
  9 f:array[0..maxe*20] of longint;
 10 p:array[0..maxe] of boolean;
 11 function min(a,b:longint):longint;
 12 begin
 13   if a>b then exit(b) else exit(a);
 14 end;
 15 procedure insert(u,v:longint);
 16 begin
 17   with bi[i] do
 18     begin
 19       f:=he[u];
 20       t:=v;
 21     end;
 22   he[u]:=i;
 23 end;
 24 procedure reinsert(u,v:longint);
 25 begin
 26   inc(cnt);
 27   with b[cnt] do
 28     begin
 29       f:=h[u];
 30       t:=v;
 31     end;
 32   h[u]:=cnt;
 33 end;
 34 procedure readd;
 35 var i,e,v:longint;
 36 begin
 37   cnt:=0;
 38   for i:=1 to n do
 39     begin
 40       e:=he[i];
 41       while e<>0 do
 42         begin
 43           v:=bi[e].t;
 44           if bl[i]<>bl[v] then reinsert(bl[i],bl[v]);
 45           e:=bi[e].f;
 46         end;
 47     end;
 48 end;
 49 procedure tarjan(x:longint);
 50 var e,t,j:longint;
 51 begin
 52   inc(dgr); inc(num);
 53   p[x]:=true; f[num]:=x; dfn[x]:=dgr; low[x]:=dgr;
 54   e:=he[x];
 55   while e<>0 do
 56     begin
 57       t:=bi[e].t;
 58       if dfn[t]=0 then
 59         begin
 60           tarjan(t);
 61           if low[x]>low[t] then low[x]:=low[t];
 62         end
 63       else if (p[t]) and (dfn[t]<low[x]) then low[x]:=dfn[t];
 64       e:=bi[e].f;
 65     end;
 66   if dfn[x]=low[x] then
 67     begin
 68       j:=0; inc(cnt);
 69       while j<>x do
 70         begin
 71           j:=f[num];
 72           dec(num);
 73           p[j]:=false;
 74           bl[j]:=cnt;
 75           //writeln(j,'   ',cnt);
 76           inc(v[cnt],va[j]);
 77         end;
 78     end;
 79 end;
 80 procedure spfa;
 81 var e,t,now,l,r:longint;
 82 begin
 83   fillchar(p,sizeof(p),true);
 84   fillchar(d,sizeof(d),0);
 85   l:=1; r:=1; f[1]:=bl[s]; p[bl[s]]:=false; d[bl[s]]:=v[bl[s]]; //writeln(v[bl[s]]);
 86   while l<=r do
 87     begin
 88       now:=f[l];
 89       e:=h[now];
 90       while e<>0 do
 91         begin
 92           t:=b[e].t;
 93           //if t=1 then writeln('x',now,' ',v[t]);
 94           if d[t]<d[now]+v[t] then
 95             begin
 96               d[t]:=d[now]+v[t];
 97               if p[t] then
 98                 begin
 99                   p[t]:=false;
100                   inc(r);
101                   f[r]:=t;
102                 end;
103             end;
104           e:=b[e].f;
105         end;
106       inc(l);
107       p[now]:=true;
108     end;
109 end;
110 begin
111   readln(n,m);
112   for i:=1 to m do
113     begin
114       readln(u,x);
115       insert(u,x);
116     end;
117   for i:=1 to n do readln(va[i]);
118   fillchar(p,sizeof(p),false);
119   for i:=1 to n do if dfn[i]=0 then tarjan(i);
120   readln(s,m);
121   readd;
122   //for i:=1 to 4 do writeln(v[i]);
123   spfa;
124   for i:=1 to m do
125     begin
126       read(u);
127       if d[bl[u]]>ans then ans:=d[bl[u]];
128     end;
129   writeln(ans);
130 end.
View Code

 (转载请注明出处:http://www.cnblogs.com/Kalenda/)

转载于:https://www.cnblogs.com/Kalenda/p/4846599.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值