dfs结合low利用递归查找最大连通块,缩环。
对图的记录和访问,对每个点用边进行链表,找路径权值最值,拓扑排序更新
#include<bits/stdc++.h>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=1e4+50;
const int M=1e5+50;
struct edge{
int from,to,nex;
}e[M],ed[M];
int head[M],n,m,uu,vv,a[N],num,dfn[N],low[N],t,stac[N],top,belong[N],in[N],ans[N],anss;
bool instack[N],vis[N];
queue<int>q;
void add(int u,int v)
{
edge ee={u,v,head[u]};
e[num]=ee;
head[u]=num++;
}
void tarjan(int u)
{
dfn[u]=low[u]=t++;
instack[u]=1;
stac[top++]=u;
for(int i=head[u];i!=-1;i=e[i].nex)
{
int v=e[i].to;
if(dfn[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
{
low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u])
{
int now;
do{
now=stac[--top];
if(now!=u)
a[u]+=a[now];
belong[now]=u;
instack[now]=0;
}while(now!=u);
}
}
int main ()
{
n=read();
m=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
}
memset(head,-1,sizeof(head));
memset(dfn,-1,sizeof(dfn));
num=0;
for(int i=1;i<=m;++i)
{
uu=read();
vv=read();
add(uu,vv);
}
t=0;
for(int i=1;i<=n;++i)
{
if(dfn[i]==-1)
tarjan(i);
}
memset(head,-1,sizeof(head));
t=0;
for(int i=0;i<num;++i)
{
int xx=e[i].from,yy=e[i].to;
xx=belong[xx],yy=belong[yy];
if(xx!=yy)
{
ed[t]=(edge){xx,yy,head[xx]};
head[xx]=t++;
in[yy]++;
}
}
for(int i=1;i<=n;++i)
{
if(belong[i]==i&&!in[i])
q.push(i),vis[i]=1,ans[i]=a[i];
}
int nn,v;
while(!q.empty())
{
nn=q.front();
q.pop();
for(int i=head[nn];i!=-1;i=ed[i].nex)
{
v=ed[i].to;
ans[v]=max(ans[v],ans[nn]+a[v]);
in[v]--;
if(!in[v]&&!vis[v])
q.push(v),vis[v]=1;
}
}
anss=0;
for(int i=1;i<=n;++i)
{
anss=max(anss,ans[i]);
}
printf("%d",anss);
return 0;
}