結果
問題 |
No.3201 Corporate Synergy
|
ユーザー |
|
提出日時 | 2025-07-11 22:03:41 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 6,836 bytes |
コンパイル時間 | 3,779 ms |
コンパイル使用メモリ | 301,592 KB |
実行使用メモリ | 6,272 KB |
最終ジャッジ日時 | 2025-07-11 22:03:57 |
合計ジャッジ時間 | 4,556 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 20 |
ソースコード
#include <bits/stdc++.h> #define fi first #define se second #define rep(i,s,n) for (int i = (s); i < (n); ++i) #define rrep(i,n,g) for (int i = (n)-1; i >= (g); --i) #define all(a) a.begin(),a.end() #define rall(a) a.rbegin(),a.rend() #define len(x) (int)(x).size() #define dup(x,y) (((x)+(y)-1)/(y)) #define pb push_back #define eb emplace_back #define Field(T) vector<vector<T>> using namespace std; using ll = long long; using ull = unsigned long long; template<typename T> using pq = priority_queue<T,vector<T>,greater<T>>; using P = pair<int,int>; template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;} template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;} class UnionFind { public: vector <int> par; vector <int> siz; int cnt; UnionFind(int sz_): par(sz_), siz(sz_, 1), cnt(sz_) { for (int i = 0; i < sz_; ++i) par[i] = i; } void init(int sz_) { par.resize(sz_); siz.assign(sz_, 1); for (int i = 0; i < sz_; ++i) par[i] = i; } int root(int x) { while (par[x] != x) { x = par[x] = par[par[x]]; } return x; } bool merge(int x, int y) { x = root(x); y = root(y); if (x == y) return false; if (siz[x] < siz[y]) swap(x, y); siz[x] += siz[y]; par[y] = x; --cnt; return true; } bool issame(int x, int y) { return root(x) == root(y); } int size(int x) { return siz[root(x)]; } int group_siz() { return cnt; } }; template <typename T> struct MaxFlow { struct edge { int to; T cap; int rev; bool is_rev; }; vector<vector<edge>> G; vector<int> dist, iter; MaxFlow() = default; explicit MaxFlow(int n) : G(n) {} void add_edge(int from, int to, T cap = 1) { G[from].emplace_back(edge{to, cap, (int)G[to].size(), 0}); G[to].emplace_back(edge{from, 0, (int)G[from].size()-1, 1}); } void debug() { for (int i = 0; i < (int)G.size(); ++i) { for (edge &e : G[i]) { if (e.is_rev) continue; edge &rev_e = G[e.to][e.rev]; cout << i << " -> " << e.to << " : " << "(" << rev_e.cap << "/" << e.cap + rev_e.cap << ")" << endl; } } } void bfs(const int &s) { dist.assign(G.size(), -1); dist[s] = 0; queue<int> que; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for (edge &e : G[v]) { if (e.cap == 0 || dist[e.to] >= 0) continue; dist[e.to] = dist[v] + 1; que.push(e.to); } } } T dfs(int v, const int &t, T f) { if (v == t) return f; T ret = 0; for (int& i = iter[v]; i < (int)G[v].size(); ++i) { edge& e = G[v][i]; if (e.cap == 0 || dist[v] >= dist[e.to]) continue; T d = dfs(e.to, t, min(f - ret, e.cap)); if (d == 0) continue; e.cap -= d; G[e.to][e.rev].cap += d; ret += d; if (f == ret) break; } return ret; } T flow(int s, int t, T f_limit = numeric_limits<T>::max()) { T ret = 0; queue<int> que; while(true) { bfs(s); if (dist[t] == -1) break; iter.assign(G.size(), 0); while(ret < f_limit) { T f = dfs(s, t, f_limit - ret); if (f == 0) break; ret += f; } } return ret; } vector<bool> min_cut(int s) { vector<bool> used(G.size(), 0); used[s] = 1; queue<int> que; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for (edge &e : G[v]) { if (e.cap > 0 && !used[e.to]) { used[e.to] = 1; que.push(e.to); } } } return used; } }; template <class T> struct BurnySolver { using table = array<T, 4>; int n; T a = T(0); vector<T> b, c; map<pair<int, int>, table> d; vector<int> flip; MaxFlow<T> G; BurnySolver(int n): n(n), b(n), c(n), flip(n, -1) { G = MaxFlow<T>(n+2); } // f == 1 -> s, f == 0 -> t void add_constraint(int i, bool f, T cost) { (f ? b[i] : c[i]) += cost; } // f == 1 -> s, f == 0 -> t void add_constraint(int i, bool fx, int j, bool fy, T cost) { if (i > j) { swap(i, j); swap(fx, fy); } d[{i, j}][2*fx+fy] += cost; } // bool == 0 -> infeasible, bool == 1 -> solved pair<T, bool> solve() { UnionFind uf(n*2); for (auto& e: d) { int i, j; tie(i, j) = e.first; const auto& t = e.second; T s = -t[0] + t[1] + t[2] - t[3]; if (s < 0) { uf.merge(i, j+n); uf.merge(i+n, j); } else if (s > 0) { uf.merge(i, j); uf.merge(i+n, j+n); } } for (int i = 0; i < n; ++i) { if (uf.issame(i, i+n)) { return {0, 0}; } if (flip[i] != -1) continue; int x = uf.root(i); int y = uf.root(i+n); if (flip[x%n] != -1) { flip[i] = int(x >= n); } else if (flip[y%n] != -1) { flip[i] = int(y < n); } else { flip[i] = 0; flip[x%n] = int(x >= n); } } for(auto &e: d) { int i, j; tie(i, j) = e.first; auto& t = e.second; if (flip[i]) { swap(t[0], t[2]); swap(t[1], t[3]); } if (flip[j]) { swap(t[0], t[1]); swap(t[2], t[3]); } T s = -t[0] + t[1] + t[2] - t[3]; a += t[0]; (flip[i] ? c[i] : b[i]) += t[2] - t[0]; (flip[j] ? c[j] : b[j]) += t[3] - t[2]; t[1] = s; t[0] = t[2] = t[3] = 0; assert(s >= 0); } for (int i = 0; i < n; ++i) { if (flip[i]) { swap(b[i], c[i]); } if (b[i] >= c[i]) { a += c[i]; b[i] -= c[i]; c[i] = 0; } else { a += b[i]; c[i] -= b[i]; b[i] = 0; } } for (int i = 0; i < n; ++i) { if (b[i] > 0) { G.add_edge(i, n+1, b[i]); } if (c[i] > 0) { G.add_edge(n, i, c[i]); } } for (auto& e: d) { int i, j; tie(i, j) = e.first; const auto& t = e.second; if (t[2] > 0) { G.add_edge(i, j, t[2]); } if (t[1] > 0) { G.add_edge(j, i, t[1]); } } return {a + G.flow(n, n+1), 1}; } vector<bool> restore() { vector<bool> ret = G.min_cut(n); rep(i,0,n) { if (flip[i]) { ret[i] = 1 - ret[i]; } } return ret; } }; static constexpr ll inf = 1000000000000000; int main() { int n; cin >> n; BurnySolver<ll> bs(n); rep(i,0,n) { int p; cin >> p; bs.add_constraint(i, 1, -p); } int m; cin >> m; rep(i,0,m) { int u, v; cin >> u >> v; --u, --v; bs.add_constraint(u, 0, v, 1, inf); } int k; cin >> k; rep(i,0,k) { int a, b, s; cin >> a >> b >> s; --a, --b; bs.add_constraint(a, 1, b, 1, -s); } cout << -bs.solve().fi << endl; return 0; }