缩点+DAG上DP
缩完点跑一遍拓扑,无后效性。真你妈神烦,调不过去。
艹调了一个小时就因为一个入度加错点了。我真傻叉。
CODE:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 10001
#define maxm 100001
int n, m, low[maxn], dfn[maxn], scc[maxn];
int tot, col, ans, top, cnt;
struct edge{
int nxt, to;
}e[maxm];
int st[maxn], dis[maxn], w[maxn], head[maxn], val[maxn], ind[maxn];
inline int read(){
int f=1, x=0;
char ch=getchar();
for(;!isdigit(ch); ch=getchar()) if(ch=='-') f=-1;
for(; isdigit(ch); ch=getchar()) x=x*10+ch-48;
return x*f;
}
void add(int u, int v){
e[++tot].nxt=head[u];
e[tot].to=v;
head[u]=tot;
}
void tarjan(int u){
dfn[u]=low[u]=++cnt;
st[++top]=u;
for(int i=head[u]; i; i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u], low[v]);
}
else if(!scc[v])
low[u]=min(low[u], dfn[v]);
}
if(low[u]==dfn[u]){
scc[u]=++col;
w[col]+=val[u];
while(st[top]!=u){
scc[st[top]]=col;
w[col]+=val[st[top--]];
}
top--;
}
}
void topo(){
queue<int>q;
for(int i=1; i<=col; i++)
if(!ind[i]){
q.push(i);
dis[i]=w[i];
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u]; i; i=e[i].nxt){
int v=e[i].to;
dis[v]=max(dis[v], dis[u]+w[v]);
ind[v]--;
if(!ind[v]) q.push(v);
}
}
ans=0;
for(int i=1; i<=n; i++)
ans=max(ans, dis[i]);
}
int x[maxm], y[maxm];
int main(){
n=read(), m=read();
for(int i=1; i<=n; i++) val[i]=read();
for(int i=1; i<=m; i++){
x[i]=read(), y[i]=read();
add(x[i], y[i]);
}
for(int i=1; i<=n; i++)
if(!dfn[i])tarjan(i);
memset(e, 0, sizeof(e));
memset(head, 0, sizeof(head));
for(int i=1; i<=m; i++)
if(scc[x[i]]!=scc[y[i]])
add(scc[x[i]], scc[y[i]]), ind[scc[y[i]]]++;
topo();
printf("%d", ans);
return 0;
}