模板-缩点
传送门 把强连通分量缩成一个点,然后对DAG跑拓扑排序,处理出最大值。 其实是【模板】缩点+【模板】拓扑排序
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define up(a,b,c) for (int a(b),end##a(c);a<=end##a;++a)
#define down(a,c,b) for (int a(b),end##a(c);a>=end##a;--a)
#define uup(a,c,b) for (int a(b),end##a(c);a<=end##a;++a)
#define udown(a,b,c) for (int a(b),end##a(c);a>=end##a;--a)
using namespace std;
int read(){
char s;
int k=0,base=1;
while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9'));
if(s==EOF)exit(0);
if(s=='-')base=-1,s=getchar();
while(s>='0'&&s<='9'){
k=k*10+(s-'0');
s=getchar();
}
return k*base;
}
void write(int x){
if(x<0){
putchar('-');
write(-x);
}
else{
if(x/10)write(x/10);
putchar(x%10+'0');
}
}
int dfn[10242],low[10242],col[10242],stk[10242],instk[10242],top,s,c,vis[10242],rd[10242],cd[10242];
int a[10242],w[10242];
int beg[10242],lst[102424],to[102424],e,beg1[10242],lst1[102424],to1[102424],e1;
int n,m;
void Tarjan(int x){//找出强连通分量,并且给每个强连通分量标号
dfn[x]=low[x]=++s;
stk[++top]=x;
instk[x]=1;
int t;
for(int i=beg[x];i;i=lst[i]){
t=to[i];
if(!dfn[t]){
Tarjan(t);
low[x]=low[x]<low[t]?low[x]:low[t];
}
else if(instk[t])low[x]=min(low[x],dfn[t]);
}
if(dfn[x]==low[x]){
++c;
do{
t=stk[top];
instk[t]=0;
col[t]=c;//col[t]表示t属于第col[t]个强连通分量
w[c]+=a[t];
--top;
}while(t!=x);
}
}
void SD(){//重新加边,缩点结束
up(i,1,n){
for(int j=beg[i];j;j=lst[j]){
if(col[i]!=col[to[j]]){
to1[++e1]=col[to[j]];
lst1[e1]=beg1[col[i]];
beg1[col[i]]=e1;
++cd[col[i]];
++rd[col[to[j]]];
}
}
}
}
int f[10242];//f[x]表示以第i个强连通分量结尾的路径权值的最大值。
int chkmax(int &a,int b){
a=a>b?a:b;
}
void Top(int x){//DFS版拓扑排序
vis[x]=1;
f[x]+=w[x];
for(int i=beg1[x];i;i=lst1[i]){
chkmax(f[to1[i]],f[x]);
if(!(--rd[to1[i]]))Top(to1[i]);
}
}
int main(){
n=read();m=read();
up(i,1,n)a[i]=read();
int u,v;
while(m){
--m;
u=read();v=read();
to[++e]=v;
lst[e]=beg[u];
beg[u]=e;
}
up(i,1,n)if(!dfn[i])Tarjan(i);
SD();
up(i,1,c)if(!vis[i]&&!rd[i])Top(i);
int ans=0;
up(i,1,c)chkmax(ans,f[i]);
printf("%d\n",ans);
return 0;
}