YACS 2023年10月月赛 甲组 题解
目前只有 T2,其他题目我在看。
T2
很简单的一道题,将图分为若干个连通块,然后分别求最小生成树。
从货车运输中得到的结论,最小生成树等价于最小边权上限生成树,也就是它也能够保证选出边中最大的边权最小。
而题目中明确说了这个最小生成树的权值是其中边权的最大值。
思路就很明显了吧,求完最小生成树后对于每个连通块预处理倍增要用的,然后先求一遍 $k$ 个点的 $lca$,把所有点到 $lca$ 路径上边的最大值取个 $\max$ 输出即可。
至于 $INF$,也很好判,最小生成树用了一个并查集,只需要判所有点的祖先是否一样即可。
代码:
#include <bits/stdc++.h> #define mp make_pair #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define foR(i, a, b) for (int i = (a); i >= (b); i --) using namespace std; int n, m, q; int c[200005], fa[200005], dep[200005]; int f[200005][18], mx[200005][18]; struct Edge {int u, v, w;}a[500005]; bool cmp (Edge e1, Edge e2) {return e1.w < e2.w;} vector <pair <int, int> > G[200005]; bool vis[200005]; int find (int x) { if (fa[x] == x) return x; return fa[x] = find (fa[x]); } void dfs (int u, int val) { vis[u] = 1; mx[u][0] = val; For (i, 1, 17) { f[u][i] = f[f[u][i - 1] ][i - 1]; mx[u][i] = max (mx[u][i - 1], mx[f[u][i - 1] ][i - 1]); } for (auto p : G[u]) { if (vis[p.first]) continue; f[p.first][0] = u; dep[p.first] = dep[u] + 1; dfs (p.first, p.second); } } int lca (int x, int y) { if (dep[x] < dep[y]) swap (x, y); foR (i, 17, 0) if (dep[f[x][i] ] >= dep[y]) x = f[x][i]; if (x == y) return x; foR (i, 17, 0) if (f[x][i] != f[y][i]) { x = f[x][i]; y = f[y][i]; } return f[x][0]; } int query (int x, int y) { int ret = 0; foR (i, 17, 0) { if (dep[f[x][i] ] >= dep[y]) { ret = max (ret, mx[x][i]); x = f[x][i]; } } return ret; } void solve () { scanf ("%d%d%d", &n, &m, &q); For (i, 1, n) fa[i] = i; For (i, 1, m) scanf ("%d%d%d", &a[i].u, &a[i].v, &a[i].w); sort (a + 1, a + m + 1, cmp); For (i, 1, m) { int fx = find (a[i].u), fy = find (a[i].v); if (fx != fy) { fa[fx] = fy; G[a[i].u].push_back (mp (a[i].v, a[i].w) ); G[a[i].v].push_back (mp (a[i].u, a[i].w) ); } } For (i, 1, n) if (!vis[i]) { dep[i] = 1; dfs (i, 0); } while (q --) { int k; scanf ("%d", &k); For (i, 1, k) scanf ("%d", &c[i]); bool fi = 0; For (i, 2, k) { if (find (c[i]) != find (c[i - 1]) ) { printf ("INF\n"); fi = 1; break; } } if (fi) continue; int l = c[1]; For (i, 2, k) l = lca (l, c[i]); int ans = 0; For (i, 1, k) ans = max (ans, query (c[i], l) ); printf ("%d\n", ans); } } signed main () { int _ = 1; // cin >> _; while (_ --) { solve (); cout << '\n'; } return 0; }