Divide each course into 0, 1, 2, 3... A [I] vertex. For each vertex with a level greater than 0, the first-level edge is raised to the vertex with a weight of 0. [This means that if level K is repaired, the level (0 ~ K) All are repaired]
Set the input edge to the value of money [I].
Create a root node and connect to the edge of each level 0. The weight is 0 because the initial level 0 has been repaired]
Because the question requires that each course reach the maximum level, that is, the root node in the corresponding graph can reach all points, the problem becomes the Minimum Spanning Tree for an undirected graph.
# Include <iostream> # include <cstdio> # include <cstring> # include <string> # include <algorithm> using namespace STD; # define INF 0x3ffffff # define maxn 5555 struct edge {int U, V, W;} e [9999999]; int N, en; int pre [maxn], in [maxn], id [maxn], vis [maxn]; void add (int u, int V, int W) {e [En]. U = u; E [En]. V = V; E [en ++]. W = W;} int ZL (INT root, int VN) {int ans = 0; int CNT; while (1) {for (INT I = 0; I <VN; I ++) in [I] = inf, Id [I] =-1, vis [I] =-1; for (INT I = 0; I <en; I ++) {If (in [E [I]. V]> E [I]. W & E [I]. U! = E [I]. v) {pre [E [I]. v] = E [I]. u; in [E [I]. v] = E [I]. W ;}} in [root] = 0; Pre [root] = root; For (INT I = 0; I <VN; I ++) {ans + = in [I]; If (in [I] = inf) Return-1;} CNT = 0; For (INT I = 0; I <VN; I ++) {If (vis [I] =-1) {int T = I; while (vis [T] =-1) {vis [T] = I; t = pre [T];} If (vis [T]! = I | T = root) continue; For (Int J = pre [T]; J! = T; j = pre [J]) ID [J] = CNT; Id [T] = CNT ++;} If (CNT = 0) break; for (INT I = 0; I <VN; I ++) if (ID [I] =-1) ID [I] = CNT ++; for (INT I = 0; I <en; I ++) {int U, V; u = E [I]. u; V = E [I]. v; E [I]. U = ID [u]; E [I]. V = ID [v]; E [I]. w-= in [v];} VN = CNT; root = ID [root];} return ans;} int A [maxn], Pres [maxn]; int main () {int X, Y, B, c, d, M; while (~ Scanf ("% d", & N, & M) {If (! N &&! M) break; For (INT I = 1; I <= N; I ++) scanf ("% d", & A [I]), pres [I] = pres [I-1] + A [I] + 1; en = 0; int S = 0; int T = pres [N] + 1; for (INT I = 1; I <= N; I ++) {for (INT id = 1; id <= A [I]; Id ++) {Add (PRES [I-1] + ID + 1, Pres [I-1] + id, 0); // printf ("% d-> % d \ n ", pres [I-1] + ID + 1, Pres [I-1] + id);} Add (S, Pres [I-1] + ); // printf ("% d-> % d \ n", Pres [I-1] + A [I] + 1, t ); // printf ("% d-> % d \ n", S, Pres [I-1] + 1);} For (INT I = 1; I <= m; I ++) {scanf ("% d", & X, & Y, & B, & C, & D ); add (PRES [x-1] + Y + 1, Pres [b-1] + C + 1, D); // printf ("% d-> % d \ n ", pres [x-1] + Y + 1, Pres [b-1] + C + 1);} int TMP = ZL (0, T); If (TMP <0) puts ("-1"); else printf ("% d \ n", TMP);} return 0 ;}