https://www.luogu.com.cn/problem/P3627
样例能过,提交全wa,我的思路是先缩点,求出缩点后每个点如果原来有休息站那么这个点就能停,每个点是那个缩的点内所有钱的总和。缩点后从s开始跑最长路。
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
int h[N],e[N<<1],ne[N<<1],idx,dfn[N],low[N];
int f[N];
int a[N],s,p,col[N],vw[N],x[N],y[N];
bool xx[N],rest[N],vis[N];
int tot=1;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int n,m;
int co=0;
stack<int> stk;
void dfs(int u,int f)
{
dfn[u]=tot++,low[u]=tot-1;
stk.push(u);
vis[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
if(!dfn[e[i]])
{
dfs(e[i],u);
low[u]=min(low[u],low[e[i]]);
}
if(vis[e[i]]) low[u]=min(low[u],dfn[e[i]]);
}
if(low[u]==dfn[u])
{
int x=-1;
co++;
while(x!=u)
{
x=stk.top();
stk.pop();
col[x]=co;
vw[co]+=a[x];
vis[x]=0;
if(xx[x]) rest[co]=1;
}
}
}
vector<int> v[N];
int dist[N];
struct node
{
int u,x;
bool operator < (const node&cmp) const
{
return x<cmp.x;
}
};
int flag[N];
priority_queue<node> q;
int main()
{
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
add(x[i],y[i]);
}
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
scanf("%d%d",&s,&p);
for(int i=1;i<=p;i++)
{
int a;
scanf("%d",&a);
xx[a]=1;
}
dfs(1,1);
for(int i=1;i<=m;i++)
{
if(col[x[i]]!=col[y[i]])
{
int a=col[x[i]],b=col[y[i]];
v[a].push_back(b);
}
}
q.push({col[s],vw[col[s]]});flag[col[s]]=1;
dist[col[s]]=vw[col[s]];
while(!q.empty())
{
node f=q.top();
q.pop();
int t=v[f.u].size();
for(int i=0;i<t;i++)
{
if(dist[f.u]+vw[v[f.u][i]]>dist[v[f.u][i]])
{
dist[v[f.u][i]]=dist[f.u]+vw[v[f.u][i]];
if(!flag[v[f.u][i]])
{
flag[v[f.u][i]]=1;
q.push({v[f.u][i],dist[v[f.u][i]]});
}
}
}
}
int mx=0;
for(int i=1;i<=co;i++)
{
if(rest[i]) mx=max(mx,dist[i]);
}
printf("%d",mx);
}