YACS 2023年10月月赛 甲组 题解

目前只有 T2,其他题目我在看。

题目链接1

题目链接2

题目链接3

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;
}

 

posted @ 2023-10-27 18:45  Xy_top  阅读(42)  评论(0编辑  收藏  举报