看到可以走多次 考虑缩点
缩点后重新建一个图跑一边spfa 速度感人
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=500000+5,inf=0x3f3f3f3f; int n,m,w[N],S,p,ans=0; int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sum[N]; stack<int>s; bool inst[N]; template<class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int head[N],tot=0; struct edge{int u,v,nxt;}e[N]; void add(int u,int v){ e[++tot]=(edge){u,v,head[u]};head[u]=tot; } void tarjan(int u){ dfn[u]=low[u]=++idx; s.push(u),inst[u]=1; for(int i=head[u],v;i;i=e[i].nxt){ v=e[i].v; if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]); else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]){ ++Bcnt; int v; do{ v=s.top(),s.pop(); bl[v]=Bcnt,sum[Bcnt]+=w[v],inst[v]=0; }while(u!=v); } } int head2[N],tot2=0; struct edge2{int v,nxt,w;}e2[N]; void add2(int u,int v,int w){ e2[++tot2]=(edge2){v,head2[u],w};head2[u]=tot2; } int dis[N];bool vis[N]; queue<int>q; void spfa(){ memset(dis,0,sizeof(dis)); q.push(bl[S]); dis[bl[S]]=sum[bl[S]],vis[S]=1; while(!q.empty()){ int u=q.front(); q.pop(),vis[u]=0; for(int i=head2[u],v,w;i;i=e2[i].nxt){ v=e2[i].v,w=e2[i].w; if(dis[v]<dis[u]+w){ dis[v]=dis[u]+w; if(vis[v]==0) q.push(v),vis[v]=1; } } } } int main(){ freopen("in.txt","r",stdin); rd(n),rd(m); for(int i=1,u,v;i<=m;++i) rd(u),rd(v),add(u,v); for(int i=1;i<=n;++i) rd(w[i]); memset(dfn,0,sizeof(dfn)); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=tot;++i) if(bl[e[i].u]!=bl[e[i].v]) add2(bl[e[i].u],bl[e[i].v],sum[bl[e[i].v]]); rd(S),rd(p); spfa(); for(int i=1,x;i<=p;++i){ rd(x); ans=max(ans,dis[bl[x]]); } printf("%d",ans); return 0; }