#include using namespace std; using ll = long long; struct edge{ int to; ll cap; int rev; }; //Dinic(0-indexed) struct MaxFlow{ private: static const ll INF=9e18; vector dist, iter; vector> idx; void bfs(int s){ int from; fill(dist.begin(), dist.end(), -1); queue que; que.push(s); dist[s] = 0; while(!que.empty()){ from = que.front(); que.pop(); for (auto &e : E[from]){ if (e.cap > 0 && dist[e.to] == -1){ dist[e.to] = dist[from] + 1; que.push(e.to); } } } } ll dfs(int s, int t, ll flow){ if (s == t) return flow; for (int &i=iter[s]; i= dist[e.to]) continue; ll d = dfs(e.to, t, min(flow, e.cap)); if (d > 0){ e.cap -= d; E[e.to][e.rev].cap += d; return d; } } return 0; } public: int N, M=0; vector> E; MaxFlow(int n) : N(n) { E.resize(N); dist.resize(N); iter.resize(N); } void add_edge(int from, int to, ll cap){ M++; idx.push_back({from, (int)E[from].size()}); E[from].push_back({to, cap, (int)E[to].size()}); E[to].push_back({from, 0, (int)E[from].size()-1}); } ll solve(int s, int t, ll limit=INF){ ll res = 0, flow; while(1){ bfs(s); if (dist[t] == -1) break; for (int i=0; i 0){ res += flow; if (res >= limit) return limit; } } return res; } //i番目の辺の(from, to, flow)を求める。 tuple get_flow(int i){ assert (i < M); edge &e = E[idx[i].first][idx[i].second]; return {idx[i].first, e.to, E[e.to][e.rev].cap}; } //最小カット(s->t)を求める vector> get_cut(int s){ vector vst(N); vector> res; auto dfs=[&](auto self, int from)->void{ vst[from] = 1; for (auto &e : E[from]){ if (vst[e.to]) continue; if (e.cap) self(self, e.to); } }; dfs(dfs, s); for (int i=0; i=0ならsource->iにP_iの損失を張る。(sinkにするとP_i損) P_i<0ならi->sinkにP_iの損失を張る。(sourceにするとP_i損) (2) V->Uに無限の損失を張る。 Vを選ぶならUも選ばないといけないから (3) source->z(A-B対)にSの損失を張る。 source->zを切らない場合A-B対は切ってはいけないのでz->A, z->Bに無限の損失を張る。 */ ll N, M, K, ans=0; cin >> N; vector P(N); for (int i=0; i> P[i]; cin >> M; vector U(M), V(M); for (int i=0; i> U[i] >> V[i]; cin >> K; vector A(K), B(K), S(K); for (int i=0; i> A[i] >> B[i] >> S[i]; MaxFlow mf(N+K+2); for (int i=0; i 0){ mf.add_edge(0, i+1, P[i]); mf.add_edge(i+1, N+K+1, 0); ans += P[i]; } else{ mf.add_edge(0, i+1, 0); mf.add_edge(i+1, N+K+1, -P[i]); } } for (int i=0; i