CF EDU 104 E - Cheap Dinner
阿新 • • 發佈:2022-05-23
E - Cheap Dinner
列舉
列舉第 2 種食物,求出每個第 2 種與第 1 種食物搭配的和的最小值,把這個最小值賦給第 2 種食物
列舉第 3 種食物,求出每個第 3 種與第 2 種食物搭配的和的最小值,把這個最小值賦給第 3 種食物
列舉第 4 種食物,求出每個第 4 種與第 3 種食物搭配的和的最小值,把這個最小值賦給第 4 種食物
答案就是最小的第 4 種食物的值
列舉的過程可先排序,比如列舉第 2 種食物的每個食物與第 1 種食物的每個食物的最小值時,如果第 1 種食物是排好序的,直接從小到大找到第一個沒被 ban 掉的就可以,因為 ban 掉的搭配只有 O(m) 級別,所以列舉的次數也是 O(m) 的
注意要用結構體存下每個食物的編號,因為排序後編號就亂了,而 ban 掉的搭配是按原始編號的
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <set> using namespace std; typedef long long ll; typedef pair<int, int> PII; const int N = 1.5e5 + 10; const ll INF = 1e18; int n1, n2, n3, n4; struct Node { int id; ll val; bool operator<(const Node &x) const { return val < x.val; } }a1[N], a2[N], a3[N], a4[N]; void solve(Node a[], Node b[], int n, int m) { int q; cin >> q; set<PII> st; while(q--) { int x, y; cin >> x >> y; st.insert({x, y}); } sort(a + 1, a + n + 1); sort(b + 1, b + m + 1); for (int i = 1; i <= m; i++) { bool flag = false; for (int j = 1; j <= n; j++) { if (!st.count({a[j].id, b[i].id})) { flag = true; b[i].val += a[j].val; break; } } if (!flag) b[i].val = INF; } } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); cin >> n1 >> n2 >> n3 >> n4; for (int i = 1; i <= n1; i++) cin >> a1[i].val, a1[i].id = i; for (int i = 1; i <= n2; i++) cin >> a2[i].val, a2[i].id = i; for (int i = 1; i <= n3; i++) cin >> a3[i].val, a3[i].id = i; for (int i = 1; i <= n4; i++) cin >> a4[i].val, a4[i].id = i; solve(a1, a2, n1, n2); solve(a2, a3, n2, n3); solve(a3, a4, n3, n4); ll ans = min_element(a4 + 1, a4 + n4 + 1)->val; if (ans < INF / 2) cout << ans << endl; else cout << -1 << endl; return 0; }