首页 > 代码库 > Codeforces 455C Civilization(并查集+dfs)

Codeforces 455C Civilization(并查集+dfs)

题目链接:Codeforces 455C Civilization

题目大意:给定N,M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的,然后是Q次操作,操作分为两种,一种是查询城市x所在的联通集合中,最长的路为多长。二是连接两个联通集合,采用联通之后最长路最短的方案。

解题思路:因为一开时的图是不可以改变的,所以一开始用dfs处理出各个联通集合,并且记录住最大值,然后就是Q次操作,用并查集维护,注意因为联通的时候要采用最长路径最短的方案,所以s的转移方程变为s = max(s, (s+1)/2 + (s0+1)/2 + 1)

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int maxn = 3 * 1e5 + 5;
int N, M, Q, f[maxn], s[maxn];
int root, ans, rec;
vector<int> g[maxn];

int getfar(int x) {
    return f[x] == x ? x : f[x] = getfar(f[x]);
}

void link (int u, int v) {
    int x = getfar(u);
    int y = getfar(v);

    if (x == y)
        return;

    if (s[x] < s[y])
        swap(s[x], s[y]);

    f[y] = x;
    s[x] = max(s[x], (s[x] + 1) / 2 + (s[y] + 1) / 2 + 1);
}

void dfs (int u, int p, int d) {
    f[u] = root;

    if (d > ans) {
        ans = d;
        rec = u;
    }

    for (int i = 0; i < g[u].size(); i++) {
        if (g[u][i] != p)
            dfs(g[u][i], u, d+1);
    }
}

int main () {
    int type, u, v;

    scanf("%d%d%d", &N, &M, &Q);
    for (int i = 1; i <= N; i++) {
        f[i] = i;
        g[i].clear();
    }

    for (int i = 0; i < M; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    for (int i = 1; i <= N; i++) {
        if (f[i] == i) {
            root = rec = i;
            ans = -1;
            dfs(i, 0, 0);

            ans = -1;
            dfs(rec, 0, 0);
            s[i] = ans;
        }
    }

    for (int i = 0; i < Q; i++) {
        scanf("%d", &type);
        if (type == 1) {
            scanf("%d", &u);
            v = getfar(u);
            printf("%d\n", s[v]);
        } else {
            scanf("%d%d", &u, &v);
            link(u, v);
        }
    }
    return 0;
}