1 #include <iostream>
2 #include <queue>
3 using namespace std;
4
5 const int MAXN = 30005;
6 const int MAXE = 150005;
7 const int inf = 0x3f3f3f3f;
8
9 typedef struct _edge
10 {
11 int v, next;
12 }E;
13 E edge[MAXE];
14 int cntEdge, head[MAXN];
15 int myS[MAXN], top;
16 int weight[MAXN], dfn[MAXN], low[MAXN], step;
17 int inS[MAXN], scc, id[MAXN];
18
19 //缩点,建DAG
20 typedef struct _node
21 {
22 int v, w, next;
23 }N;
24 N sccEdge[MAXE];
25 int sccHead[MAXN], sccCntEdge;
26 int idw[MAXN], in[MAXN], out[MAXN];
27
28 void init()
29 {
30 top = 0;
31 step = cntEdge = sccCntEdge = 0;
32 scc = 1;
33 for(int i = 0; i < MAXN; i++)
34 {
35 myS[i] = 0;
36 in[i] = out[i] = 0;
37 weight[i] = 0;
38 id[i] = -1;
39 sccHead[i] = head[i] = -1;
40 inS[i] = idw[i] = 0;
41 dfn[i] = low[i] = -1;
42 }
43 }
44
45 void addEdge(int u, int v)
46 {
47 edge[cntEdge].v = v;
48 edge[cntEdge].next = head[u];
49 head[u] = cntEdge++;
50 }
51
52 void tarjan_scc(int n)
53 {
54 dfn[n] = low[n] = ++step;
55 myS[top++] = n;
56 inS[n] = 1;
57 for(int f = head[n]; f != -1; f = edge[f].next)
58 {
59 int son = edge[f].v;
60 if(dfn[son] == -1)
61 {
62 tarjan_scc(son);
63 low[n] = min(low[n], low[son]);
64 }
65 else if(inS[son] == 1)
66 low[n] = min(low[n], dfn[son]);
67 }
68
69 if(low[n] == dfn[n] && top != 0)
70 {
71 int tmp;
72 do
73 {
74 tmp = myS[--top];
75
76 inS[tmp] = 0;
77 id[tmp] = scc;
78 idw[scc] += weight[tmp];
79
80 }while(top != 0 && tmp != n);
81 scc++;
82 }
83 }
84
85 int spfa(int s)
86 {
87 int dis[MAXN], inQ[MAXN] = {0};
88 for(int i = 0; i < MAXN; i++)
89 dis[i] = -inf;
90 queue<int> Q;
91
92 Q.push(s);
93 dis[s] = 0;
94 inQ[s] = 1;
95
96 while(!Q.empty())
97 {
98 int pre = Q.front();
99 Q.pop();
100 inQ[pre] = 0;
101
102 for(int i = sccHead[pre]; i != -1; i = sccEdge[i].next)
103 {
104 int son = sccEdge[i].v, w = sccEdge[i].w;
105 if(dis[son] < dis[pre] + w)
106 {
107 dis[son] = dis[pre] + w;
108 if(inQ[son] == 0)
109 {
110 Q.push(son);
111 inQ[son] = 1;
112 }
113 }
114 }
115 }
116
117 int Max = 0;
118 for(int i = 1; i < scc; i++)
119 {
120 if(out[i] == 0)
121 {
122 if(dis[i] > Max)
123 Max = dis[i];
124 }
125 }
126 return Max;
127 }
128
129 void bulid_scc(int n, int &sol)
130 {
131 int u, v;
132 for(int i = 0; i < n; i++)
133 {
134 for(int j = head[i]; j != -1; j = edge[j].next)
135 {
136 u = i, v = edge[j].v;
137 if(id[u] == id[v])
138 continue;
139 else
140 {
141 sccEdge[sccCntEdge].v = id[v];
142 sccEdge[sccCntEdge].w = idw[id[v]];
143 sccEdge[sccCntEdge].next = sccHead[id[u]];
144 sccHead[id[u]] = sccCntEdge++;
145
146 in[id[v]]++;
147 out[id[u]]++;
148 }
149 }
150 }
151
152 int Max = 0;
153 for(int i = 1; i < scc; i++)
154 {
155 if(in[i] == 0)
156 {
157 sccEdge[sccCntEdge].v = i;
158 sccEdge[sccCntEdge].w = idw[i];
159 sccEdge[sccCntEdge].next = sccHead[0];
160 sccHead[0] = sccCntEdge++;
161
162 }
163 }
164
165 sol = spfa(0);
166 return ;
167 }
168
169 int main(void)
170 {
171 #ifndef ONLINE_JUDGE
172 freopen("in.txt", "r", stdin);
173 #endif
174
175 int n, m;
176 while(scanf("%d %d", &n, &m) == 2)
177 {
178 int u, v, t;
179 init();
180 for(int i = 0; i < n; i++)
181 {
182 scanf("%d", &t);
183 if(t > 0)
184 weight[i] = t;
185 else
186 weight[i] = 0;
187 }
188 for(int i = 0; i < m; i++)
189 {
190 scanf("%d %d", &u, &v);
191 addEdge(u, v);
192 }
193 for(int i = 0; i < n; i++)
194 {
195 if(dfn[i] == -1)
196 tarjan_scc(i);
197 }
198 int sol;
199 bulid_scc(n, sol);
200 printf("%d\n", sol);
201 }
202 return 0;
203 }