Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Ignore the costs for a second. If you start at some employee and keep moving to their supervisor, how do the qualifications change along that path?
Because every allowed edge satisfies , any chosen supervisor chain is strictly increasing in when followed upward. So ask yourself: can a directed cycle even exist here?
Who can be the root? Any employee with maximum qualification has no possible supervisor, because nobody has strictly larger . So if the maximum value appears more than once, you're already screwed: you'd get at least two roots.
Suppose there is a unique employee with maximum qualification. Then every other employee just needs exactly one incoming edge from some higher-qualified employee. Since cycles are impossible anyway, the choice for one vertex does not interfere with the choice for another.
The answer is simply
where is the unique employee with maximum qualification. If there is no such unique , or some has no incoming application at all, output . That's it — no MST black magic, no Edmonds, no DSU cosplay.
This problem looks like it wants some scary directed-tree algorithm. It doesn't. The qualification constraint completely neuters the hard part.
For every allowed application , we know
So if chooses as its supervisor, then moving upward in the hierarchy strictly increases qualification.
That immediately implies:
So the usual headache of "what if my parent choices create a cycle?" is gone. Dead. Buried.
Who can be the root?
Any employee with maximum qualification cannot have a supervisor at all, because there is no employee with strictly larger qualification.
Therefore:
So a necessary condition is:
And if that holds, is forced to be the root.
Now fix that unique root .
Every other employee must choose exactly one supervisor, i.e. exactly one incoming application .
Since cycles cannot happen, the choices for different vertices are completely independent. There is no global interaction left. For each vertex , we should simply take the cheapest incoming edge.
So the optimal answer is
If some employee has no incoming application at all, then building the hierarchy is impossible.
After choosing one incoming edge for every employee except :
Follow supervisor pointers upward from any node. Qualifications strictly increase, so the chain cannot continue forever and cannot cycle. It must end at a node with no supervisor. But there is only one such node: .
Hence every employee reaches , so all employees belong to the same rooted tree.
We scan the employees once and the applications once.
Very cheap. Almost suspiciously cheap. But the strict qualification order is doing all the heavy lifting.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() { setIO();
int n;
cin >> n;
vector<int> q(n + 1);
int mx = -1, root = -1, cntMax = 0;
for (int i = 1; i <= n; ++i) {
cin >> q[i];
if (q[i] > mx) {
mx = q[i];
root = i;
cntMax = 1;
} else if (q[i] == mx) {
++cntMax;
}
}
int m;
cin >> m;
const ll INF = (1LL << 60);
vector<ll> best(n + 1, INF);
for (int i = 0; i < m; ++i) {
int a, b;
ll c;
cin >> a >> b >> c;
// The statement guarantees q[a] > q[b], but checking doesn't hurt.
if (q[a] > q[b]) best[b] = min(best[b], c);
}
if (cntMax != 1) {
cout << -1 << '\n';
return 0;
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
if (i == root) continue;
if (best[i] == INF) {
cout << -1 << '\n';
return 0;
}
ans += best[i];
}
cout << ans << '\n';
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() { setIO();
int n;
cin >> n;
vector<int> q(n + 1);
int mx = -1, root = -1, cntMax = 0;
for (int i = 1; i <= n; ++i) {
cin >> q[i];
if (q[i] > mx) {
mx = q[i];
root = i;
cntMax = 1;
} else if (q[i] == mx) {
++cntMax;
}
}
int m;
cin >> m;
const ll INF = (1LL << 60);
vector<ll> best(n + 1, INF);
for (int i = 0; i < m; ++i) {
int a, b;
ll c;
cin >> a >> b >> c;
// The statement guarantees q[a] > q[b], but checking doesn't hurt.
if (q[a] > q[b]) best[b] = min(best[b], c);
}
if (cntMax != 1) {
cout << -1 << '\n';
return 0;
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
if (i == root) continue;
if (best[i] == INF) {
cout << -1 << '\n';
return 0;
}
ans += best[i];
}
cout << ans << '\n';
}