Codeforces 455C Civilization(並查集+dfs),codeforces455c
題目連結: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;}