首先我们可以将这个图缩成DAG,那么问题中的路线就可以简化为DAG中的一条链,那么我们直接做一遍spfa就好了。
反思:开始写的bfs,结果bfs的时候没有更新最大值,而是直接赋的值,后来发现不能写bfs,因为每个点可能进队好多次,当让可以改成循环队列什么的bfs,然后我就改成了spfa,伪的spfa,就是判一下这个点是不是更优了,更优才入队。
/************************************************************** Problem: 1179 User: BLADEVIL Language: C++ Result: Accepted Time:6640 ms Memory:109356 kb ****************************************************************/ //By BLADEVIL #include <cstdio> #include <cstring> #include <algorithm> #define maxm 2000010 #define maxn 2000010 using namespace std; int n,m,s,tot,time,num,p,l; int pre[maxm],other[maxm],last[maxn],key[maxn],flag[maxn]; int stack[maxn],dfn[maxn],low[maxn],vis[maxn],col[maxn],que[maxn],w[maxn]; void connect(int x,int y) { pre[++l]=last[x]; last[x]=l; other[l]=y; } void dfs(int x) { stack[++tot]=x; vis[x]=1; dfn[x]=low[x]=++time; for (int p=last[x];p;p=pre[p]) { if (!dfn[other[p]]) dfs(other[p]),low[x]=min(low[x],low[other[p]]); else if (vis[other[p]]) low[x]=min(low[x],dfn[other[p]]); } if (dfn[x]==low[x]) { int cur=-1; num++; while (cur!=x) { cur=stack[tot--]; vis[cur]=0; col[cur]=num; } } } int main() { scanf("%d%d",&n,&m); num=n; for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); connect(x,y); } for (int i=1;i<=n;i++) scanf("%d",&key[i]); scanf("%d%d",&s,&p); while (p--) { int x; scanf("%d",&x); flag[x]=1; } dfs(s); for (int i=1;i<=n;i++) { for (int p=last[i];p;p=pre[p]) if (col[i]!=col[other[p]]) connect(col[i],col[other[p]]); } for (int i=1;i<=n;i++) key[col[i]]+=key[i],flag[col[i]]|=flag[i]; memset(vis,0,sizeof vis); que[1]=col[s]; vis[col[s]]=1; w[col[s]]=key[col[s]]; int h=0,t=1,ans=0; while (h<t) { int cur=que[++h]; if (flag[cur]) ans=max(ans,w[cur]); for (int p=last[cur];p;p=pre[p]) { if (w[cur]+key[other[p]]>w[other[p]]) { w[other[p]]=max(w[other[p]],w[cur]+key[other[p]]); que[++t]=other[p]; vis[other[p]]=1; } } } printf("%d ",ans); return 0; }