本题的题意为 给n个点m条单向边 然后再给出0~n个点的点权(有正有负)
要求是 从某一点开始走,走到一个点:可以选择进去,获得点权(只能进一次)或者选择绕过这个点继续走,求能获得的最大权值

我的做法:强连通缩点+bfs

//author: CHC
//First Edit Time: 2014-06-13 20:26
//Last Edit Time: 2014-06-13 20:26
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define TMAXN 30010
vector <int> e[TMAXN];
vector <int> e1[TMAXN];
int dfn[TMAXN],low[TMAXN],stack[TMAXN],bleg[TMAXN];
int top,times,n;
void tarjan_x(int u){
dfn[u]=low[u]=++times;
stack[++top]=u;
for(int i=0;i<(int)e[u].size();i++){
int v=e[u][i];
if(!dfn[v]){
tarjan_x(v);
low[u]=min(low[u],low[v]);
}
else if(!bleg[v])
low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u]){
bleg[0]++;
do{
bleg[stack[top]]=bleg[0];
}while(stack[top--]!=u);
}
}
void initstat(){
memset(dfn,0,sizeof(dfn));
memset(bleg,0,sizeof(bleg));
top=times=0;
}
void tarjan(int n){
initstat();
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan_x(i);
}
void inite(){
for(int i=0;i<TMAXN;i++)e[i].clear();
for(int i=0;i<TMAXN;i++)e1[i].clear();
}
#define INF_MAX -0x7fffffff
int val[TMAXN];
int vall[TMAXN];
int dis[TMAXN];
queue <int> q;
int bfs(int u){
while(!q.empty())q.pop();
q.push(u);
dis[u]=vall[u];
int mm=INF_MAX;
//printf("hhere\n");
while(!q.empty()){
int now=q.front();
q.pop();
if(dis[now]>mm)mm=dis[now];
//printf("hhere\n");
//printf("now:%d\n",dis[now]);
for(int i=0;i<(int)e1[now].size();i++){
int next=e1[now][i];
if(dis[now]+vall[next]>dis[next]){
dis[next]=dis[now]+vall[next];
q.push(next);
}
}
}
return mm;
}
int main()
{
int n,m;
//printf("%d\n",INF_MAX);
while(~scanf("%d%d",&n,&m)){
inite();
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
}
for(int i=0,x,y;i<m;i++){
scanf("%d%d",&x,&y);
e[x+1].push_back(y+1);
}
tarjan(n);
memset(vall,0,sizeof(vall));
for(int i=1;i<=n;i++){
if(val[i]>0)
vall[bleg[i]]+=val[i];
for(int j=0;j<(int)e[i].size();j++){
int v=e[i][j];
if(bleg[i]!=bleg[v]){
e1[bleg[i]].push_back(bleg[v]);
}
}
}
for(int i=0;i<TMAXN;i++){
dis[i]=INF_MAX;
}
int mm=INF_MAX;
for(int i=1;i<=bleg[0];i++){
if(dis[i]==INF_MAX){
//printf("here\n");
int t=bfs(i);
//printf("t:%d\n",t);
if(t>mm)mm=t;
}
}
printf("%d\n",mm);
}
return 0;
}