#ifdef LOCAL #include"algo/debug.h" #else #define debug(...) 42 #endif
intmain(){ ios::sync_with_stdio(false); cin.tie(0); int tt; cin >> tt; while (tt--) { int n, d; longlong c; cin >> n >> c >> d; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.rbegin(), a.rend()); int low = -1, high = d + 1; while (low < high) { int mid = (low + high + 1) >> 1; longlong sum = 0; for (int i = 0; i < d; i++) { int id = i % (mid + 1); if (id < n) { sum += a[id]; } } if (sum >= c) { low = mid; } else { high = mid - 1; } } if (low == d + 1) { cout << "Infinity" << '\n'; } else { if (low == -1) { cout << "Impossible" << '\n'; } else { cout << low << '\n'; } } } return0; }
G. SlavicG’s Favorite Problem
题意:有一个无根树,你初始在 a,有一个变量 x 初始为 0,每经过一条边都会异或上该边的边权。你能到达点 b 当且仅当 x 到达 b 时恰好为 0。你可以在任意时刻传送到任意位置一次(除了点 b),问是否能到达点 b。
可以进行两遍搜索,一遍从 a 开始但不能走 b,一遍从 b 开始。判断是否能存在两个点 i,j,使得 i 到 a 的距离和 j 到 b 的距离相等(此时可以 a→i⇒j→b。用 set 维护即可。
#ifdef LOCAL #include"algo/debug.h" #else #define debug(...) 42 #endif
intmain(){ ios::sync_with_stdio(false); cin.tie(0); int tt; cin >> tt; while (tt--) { int n, a, b; cin >> n >> a >> b; --a; --b; vector<vector<pair<int, int>>> g(n); for (int i = 0; i < n - 1; i++) { int x, y, w; cin >> x >> y >> w; --x; --y; g[x].emplace_back(y, w); g[y].emplace_back(x, w); } vector<int> d(n, -1); vector<int> que(1, a); d[a] = 0; for (int it = 0; it < (int) que.size(); it++) { for (auto& p : g[que[it]]) { int u = p.first; if (d[u] == -1 && u != b) { que.push_back(u); d[u] = d[que[it]] ^ p.second; } } } set<int> all; for (int i = 0; i < n; i++) { if (d[i] != -1) { all.insert(d[i]); } } d.assign(n, -1); que.assign(1, b); d[b] = 0; for (int it = 0; it < (int) que.size(); it++) { for (auto& p : g[que[it]]) { int u = p.first; if (d[u] == -1) { que.push_back(u); d[u] = d[que[it]] ^ p.second; } } } bool ok = false; for (int i = 0; i < n; i++) { if (i != b) { if (all.find(d[i]) != all.end()) { ok = true; break; } } } cout << (ok ? "YES" : "NO") << '\n'; } return0; }