tarjan求强连通分量后缩点,缩点后点权为原来的点之和,是否为酒吧为原来的点的或。然后做点权最长路的spfa,为酒吧的点中的最大值即为答案。
代码:
type
edge=^edgenode;
edgenode=record
t:longint;
next:edge;
end;
var
n,m,i,x,y,z,s,p,num,time,top,ans:longint;
con:array[0..500100,0..1]of edge;
w,col,dfn,low,st,dl,dist:array[0..500100]of longint;
en,visit:array[0..500100]of boolean;
procedure ins(x,y,b:longint);
var
p:edge;
begin
new(p);
p^.t:=y;
p^.next:=con[x,b];
con[x,b]:=p;
end;
function min(x,y:longint):longint;
begin
if x>y then exit(y)
else exit(x);
end;
procedure tarjan(v:longint);
var
i:longint;
p:edge;
begin
inc(time);
dfn[v]:=time;
low[v]:=time;
visit[v]:=true;
p:=con[v,0];
inc(top);
st[top]:=v;
while p<>nil do
begin
if col[p^.t]>0 then begin p:=p^.next; continue; end;
if visit[p^.t]=false then
begin
tarjan(p^.t);
low[v]:=min(low[v],low[p^.t]);
end
else low[v]:=min(low[v],dfn[p^.t]);
p:=p^.next;
end;
if low[v]=dfn[v] then
begin
inc(num);
while st[top+1]<>v do
begin
col[st[top]]:=num;
dec(top);
end;
end;
end;
procedure rebuild;
var
i:longint;
p:edge;
begin
for i:=1 to n do
begin
p:=con[i,0];
while p<>nil do
begin
if col[i]<>col[p^.t] then ins(col[i],col[p^.t],1);
p:=p^.next;
end;
end;
end;
procedure spfa;
var
head,tail,x:longint;
p:edge;
begin
head:=1;
tail:=1;
dl[1]:=col[s];
fillchar(dist,sizeof(dist),0);
dist[col[s]]:=w[col[s]];
fillchar(visit,sizeof(visit),false);
visit[col[s]]:=true;
while head<=tail do
begin
x:=dl[head];
p:=con[x,1];
while p<>nil do
begin
if dist[p^.t]<dist[x]+w[p^.t] then
begin
dist[p^.t]:=dist[x]+w[p^.t];
if not visit[p^.t] then
begin
inc(tail);
dl[tail]:=p^.t;
visit[p^.t]:=true;
end;
end;
p:=p^.next;
end;
visit[x]:=false;
inc(head);
end;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y);
ins(x,y,0);
end;
for i:=1 to n do
if not visit[i] then tarjan(i);
rebuild;
for i:=1 to n do
begin
readln(x);
inc(w[col[i]],x);
end;
readln(s,p);
for i:=1 to p do
begin
read(x);
en[col[x]]:=true;
end;
spfa;
ans:=0;
for i:=1 to num do
if en[i] and (ans<dist[i]) then ans:=dist[i];
writeln(ans);
end.