缩点求DAG最长路
tarjan缩点:给一个强连通分量内的点打标记,缩为新的点,建立新的图( DAG )
#include <bits/stdc++.h> using namespace std ; const int N=1e4+2; int n,m,a[N]; int pool,low[N],dfn[N]; int cl,col[N]; int f[N],val[N]; vector<int> g[N],graph[N]; stack<int> st; void tarjan(int x){ st.push(x); dfn[x]=low[x]=++pool; int i,y; for(i=0;i<g[x].size();i++){ y=g[x][i]; if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if(!col[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ cl++; do{ y=st.top(); st.pop(); col[y]=cl; }while(x!=y); } } int dp(int x){ if(f[x]!=-1) return f[x]; f[x]=val[x]; for(int i=0,y;i<graph[x].size();i++){ y=graph[x][i]; f[x]=max(f[x],val[x]+dp(y)); } return f[x]; } int main(){ int i,j,x,y,t=0; cin>>n>>m; for(i=1;i<=n;i++) cin>>a[i]; for(i=1;i<=m;i++) cin>>x>>y,g[x].push_back(y); for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(i=1;i<=n;i++) val[col[i]]+=a[i]; for(i=1;i<=n;i++) for(j=0;j<g[i].size();j++){ x=col[i],y=col[g[i][j]]; if(x!=y) graph[x].push_back(y); } for(i=1;i<=cl;i++) f[i]=-1; for(i=1;i<=cl;i++) t=max(t,dp(i)); cout<<t; }