結果
| 問題 |
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;
}